【问题标题】:Add the first line to the beginning of a file to each line with shell用shell将第一行添加到文件的开头到每一行
【发布时间】:2018-02-05 23:15:24
【问题描述】:

我有很多文件,它们的第一行作为标识符。随后的行是标识符的产品。这是文件的一个示例:

0G000001:
Product_2221
Product_2222
Product_2122
...

我想把标识符放在文件每一行的开头。最终输出是这样的:

0G000001: Product_2221
0G000001: Product_2222
0G000001: Product:2122
....

我想为我拥有的所有文件创建一个循环。我一直在尝试:

for i in $(echo `head -n1 file.$i.txt);
    do
cat - file.$i.txt > file_id.$i.txt;
done

但我只复制文件的第一行。我知道 sed 可以在文件开头添加特定文本,但我无法确定该文本是文件的第一行并在 循环中 em>上下文。

【问题讨论】:

  • sed 用于s/old/new/。你没有在做s/old/new/,所以你不应该考虑使用 sed。对于其他任何事情,只需使用 awk 来获得更简单、更清晰、更高效、更健壮、更便携、更可扩展等...解决方案。

标签: shell loops awk sed append


【解决方案1】:

awk:

awk 'NR==1 { prod = $0 } NR>1 { print prod, $0 }' infile

输出:

0G000001: Product_2221
0G000001: Product_2222
0G000001: Product_2122

【讨论】:

  • 如果有多个文件,FNR 会更好。
  • @TomFenech:是的,但这需要更多代码来处理写出结果。有关该解决方案,请参阅Ed's answer
【解决方案2】:

这可能对你有用(GNU sed):

sed -ri '1h;1d;G;s/(.*)\n(.*)/\2 \1/' file ...

将第一行保存在保持空间 (HS) 中,然后将其从模式空间 (PS) 中删除。对于每一行(第一行除外),将 HS 附加到 PS,然后交换行并用空格替换换行符。

【讨论】:

    【解决方案3】:

    执行您想要的操作的 sed 命令可能如下所示:

    $ sed '1{h;d};G;s/\(.*\)\n\(.*\)/\2 \1/' infile
    0G000001: Product_2221
    0G000001: Product_2222
    0G000001: Product_2122
    

    执行以下操作:

    1 {                       # On the first line
        h                     # Copy the pattern space to the hold space
        d                     # Delete the line, move to next line
    }
    G                         # Append the hold space to the pattern space
    s/\(.*\)\n\(.*\)/\2 \1/   # Swap the lines in the pattern space
    

    一些 sed 可能会抱怨 {h;d} 并需要一个额外的分号 {h;d;}

    要对文件就地执行此操作,您可以使用

    sed -i '1{h;d};G;s/\(.*\)\n\(.*\)/\2 \1/' infile
    

    对于 GNU sed,或

    sed -i '' '1{h;d};G;s/\(.*\)\n\(.*\)/\2 \1/' infile
    

    对于 macOS sed。或者,如果您的 sed 根本不支持 -i

    sed '1{h;d};G;s/\(.*\)\n\(.*\)/\2 \1/' infile > tmpfile && mv tmpfile infile
    

    循环遍历目录中的所有文件:

    for f in /path/to/dir/*; do
        sed -i '1{h;d};G;s/\(.*\)\n\(.*\)/\2 \1/' "$f"
    done
    

    甚至直接使用 glob:

    sed -i '1{h;d};G;s/\(.*\)\n\(.*\)/\2 \1/' /path/to/dir/*
    

    后者肯定适用于 GNU sed;不知道其他seds。

    【讨论】:

      【解决方案4】:

      sed + head 解决方案:

      for f in *.txt; do sed -i '1d; s/^/'"$(head -n1 $f)"' /' "$f"; done
      

      • -i - 就地修改文件

      • 1d; - 删除第一行

      • $(head -n1 $f) - 从文件中提取第一行(获取标识符)

      • s/^/<identifier> / - 将标识符添加到文件中的每一行

      【讨论】:

        【解决方案5】:

        无需显式循环:

        awk '
            FNR==1 { close(out); out=FILENAME; sub(/\./,"_id&",out); hdr=$0; next }
            { print hdr, $0 > out }
        ' file.*.txt
        

        【讨论】:

          猜你喜欢
          • 2012-01-02
          • 2019-09-11
          • 1970-01-01
          • 1970-01-01
          • 2021-01-22
          • 1970-01-01
          • 2015-10-03
          相关资源
          最近更新 更多