【问题标题】:awk sed help needed to create a file创建文件所需的 awk sed 帮助
【发布时间】:2014-05-23 06:23:48
【问题描述】:

您好,我有一个包含条目的输入文件。每行都以主机名 (host1, host2) 开头。 我需要在主机名之后创建一个文件名,该文件名将包含冒号后每一行的条目列表。有人可以帮忙吗?请看下面的例子

输入文件

host1*stop*start : runit stopit gather 
host2*stop*start : unite cease cut chop eat

输出文件名host1

runit 
stopit 
gather 

输出文件名host2

unite 
cease 
cut 
chop 
eat

【问题讨论】:

    标签: linux bash sed awk tr


    【解决方案1】:

    使用perl

    perl -lane '$,="\n";$F[0]=~/([^*]+)/;open(O,">$1");print O @F[2..$#F];close(O)' file
    

    使用 cmets:

    perl -lane '             # Split the line on space and load them in an array
        $,="\n";             # Set the output list separator to newline
        $F[0] =~ /([^*]+)/;  # Capture the file name from first array index
        open(O,">$1");       # Open a file handle with filename using captured group
        print O @F[2..$#F];  # print everything from 3rd index to end of line in that file
        close(O)             # Close the file handle
    ' file
    

    【讨论】:

    • 感谢这也有效。不知道如何..但谢谢你
    • @theuniverseisflat 不客气。我为你添加了一些 cmets。希望对您有所帮助。
    【解决方案2】:
    awk '{n=split($1,array,"*"); for (i=3;i<=NF;i++) {print $i >array[1]}}' input
    

    以上使用空格作为字段分隔符。因此,对于您的第一个示例行,第一个字段是 host1*stop*start,第二个字段是 :,其余的是:runitstopitgather。我们首先需要从第一个字段中提取主机名。我们通过在字符* 上拆分该字段来做到这一点,这会将主机名放在变量array[1] 中。然后,我们将第三个字段以及之后的所有字段作为单独的行写入以array[1] 命名的文件。

    【讨论】:

    • ITYM &gt;,而不是 &gt;&gt;。 awk 语义与 shell 不同。无需保存 split() 返回代码,并且 split 将 RE 作为 arg,因此除非出于某种原因使用包含在字符串中的 RE,否则应使用 // 分隔符以保持清晰和简单(对于更复杂的 RE) .顺便说一下 +1 :-)。
    • @EdMorton 谢谢。是的,n= 是可选的。顺便说一句,我检查了GNU awk manual,它说 >> 应该用于追加(See Sec. 5.6),尽管在这种情况下 > 保护用户免受代码的多次运行(所做的更改)。也根据手册秒。在 9.1.3 中,split 的第三个参数称为 fieldsep,并且在 Sec 6.1.2 中,手册指出只有现代版本的 awk 允许在那里使用正则表达式。
    • &gt;&gt; 用于当您特别需要附加到现有文件时,当您只想按照 OP 所述创建文件时,则为 &gt;。是的,第三个参数在手册页中被命名为 fieldsep ,它是一个 RE,其处理方式与 FS wrt 字段拆分中的 RE 相同(例如,专门处理单个空格字符),我知道的唯一 awk 可能不会允许一个 RE 常量,有一个旧的、损坏的 awk 永远不应该使用。如果您改为指定一个字符串,那么您需要担心 awk 对其进行双重解析,因此需要将您希望作为文字的 RE 元字符双引号。
    【解决方案3】:

    仅使用 内置函数:

    while IFS=: read -a ln; do
        printf "%s\n" ${ln[@]:1} > "${ln[0]%%\**}"
    done < file.txt
    
    • 读取: 上的每一行并将其拆分为一个数组
    • 数组的第 0 个元素将是例如“主机1*停止*开始”。通过使用参数扩展删除每个* 和所有后续文本,这将变成所需的文件名
    • 所有剩余元素将是一个以空格分隔的列表。这被传递给 printf,它将根据其格式说明符格式化该列表的每个成员
    • printf 输出被重定向到上面生成的文件名

    【讨论】:

      猜你喜欢
      • 2018-04-04
      • 1970-01-01
      • 2022-10-24
      • 2014-01-21
      • 1970-01-01
      • 2015-01-12
      • 1970-01-01
      • 2015-11-04
      • 1970-01-01
      相关资源
      最近更新 更多