【问题标题】:Add prefix to every line in text in bash为bash中文本的每一行添加前缀
【发布时间】:2013-11-18 20:32:06
【问题描述】:

假设有一个文本文件a.txt 例如

啊啊啊 bbb ccc ddd

我需要在文件的每一行添加一个前缀(例如myprefix_):

myprefix_aaa myprefix_bbb myprefix_ccc myprefix_ddd

我可以用 awk 做到这一点:

awk '{print "myprefix_" $0}' a.txt 

现在我想知道在 shell 中是否有其他方法可以做到这一点。

【问题讨论】:

  • 你可以只用bash(而不是调用sed/awk/perl/python/etc作为外部可执行文件)但你最好使用最好的工具来完成这项工作,对于这个简单的情况,可能是sedawk.
  • 我完全同意,awk 看起来有点矫枉过正,这就是我问这个问题的原因。 bash 你会怎么做?
  • 我不会。我会用sed 来做这件事,就像@fedorqui 所展示的那样。

标签: bash text awk


【解决方案1】:

sed:

$ sed 's/^/myprefix_/' a.txt
myprefix_aaa
myprefix_bbb
myprefix_ccc
myprefix_ddd

这会将以myprefix_ 开头的每一行替换为^。请注意,^ 不会丢失,因此可以在每行的开头添加内容。

您可以使用以下方法缩短您的 awk 版本:

$ awk '$0="myprefix_"$0' a.txt
myprefix_aaa
myprefix_bbb
myprefix_ccc
myprefix_ddd

或传递值:

$ prefix="myprefix_"
$ awk -v prefix="$prefix" '$0=prefix$0' a.txt
myprefix_aaa
myprefix_bbb
myprefix_ccc
myprefix_ddd

也可以使用nl:

$ nl -s "prefix_" a.txt | cut -c7-
prefix_aaa
prefix_bbb
prefix_ccc
prefix_ddd

最后:作为John Zwinck explains,你也可以这样做:

paste -d'' <(yes prefix_) a.txt | head -n $(wc -l a.txt)

在 OS X 上:

paste -d '\0' <(yes prefix_) a.txt | head -n $(wc -l < a.txt)

【讨论】:

  • +1 表示sed 解决方案,其中使用awkPerl 就像用热核弹头拍蚊子:-)
  • 谢谢!我喜欢sed 解决方案,但不知道nl
  • 或惊恐:paste -d'' &lt;(yes prefix_) a | head -n $(wc -l a)。如果 paste 可以选择在第一个 EOF 处停止而不是一直持续到所有 EOF,那会好很多。
  • 这是一个适用于 OS X 的版本:paste -d '\0' &lt;(yes prefix_) a.txt | head -n $(wc -l &lt; a.txt) - 在 Linux 上,您可能需要说 '' 而不是 '\0',但其余的应该都可以。
  • 您的nl 解决方案非常棒,我稍微改进了它以使其稳定和通用,---------@ 987654345@
【解决方案2】:

纯 bash:

while read line
do
    echo "prefix_$line"
done < a.txt

【讨论】:

    【解决方案3】:

    作为参考,关于awksedbash解决这个问题的速度:

    bash中生成一个800K的输入文件:

    line="12345678901234567890123456789012345678901234567890123456789012345678901234567890"
    rm a.txt
    for i in {1..10000} ; do
        echo $line >> a.txt
    done
    

    然后考虑bash脚本timeIt

    if [ -e b.txt ] ; then
        rm b.txt
    fi
    echo "Bash:"
    time bashtest
    rm b.txt
    echo
    echo "Awk:"
    time awktest
    rm b.txt
    echo
    echo "Sed:"
    time sedtest
    

    bashtest 在哪里

    while read line
    do
        echo "prefix_$line" >> b.txt
    done < a.txt
    

    awktest 是:

    awk '$0="myprefix_"$0' a.txt > b.txt
    

    sedtest 是:

    sed 's/^/myprefix_/' a.txt > b.txt
    

    我在我的机器上得到了以下结果:

    Bash:
    
    real    0m0.401s
    user    0m0.340s
    sys 0m0.048s
    
    Awk:
    
    real    0m0.009s
    user    0m0.000s
    sys 0m0.004s
    
    Sed:
    
    real    0m0.009s
    user    0m0.000s
    sys 0m0.004s
    

    似乎bash 解决方案要慢得多..

    【讨论】:

    • +1 生成外部程序是 shell 语言的目的。如果您每行调用一次awk 来为其添加前缀,那将是矫枉过正。但是调用一次来处理整个文件就可以了。
    • @Psyrus 同意。谢谢你的评论!随时使用新的计时结果更新答案..
    • 我已经调查过了,不会编辑答案,因为事实证明,使用 bash 在内存中进行字符串连接的速度是您根据我的测试提出的方法的两倍(并且因为字符串连接是出了名的糟糕,实际上是有道理的)。顺便说一句,一个很好的答案,+1
    • 作为参考,我使用的代码:for line in $(&lt;a.txt); do; text+="prefix_$line\n"; done; echo -e "$text" &gt; b.txt; 尝试了各种调整,结果要么更差,要么相似
    【解决方案4】:

    您也可以使用xargs 实用程序:

    cat file | xargs -d "\n" -L1 echo myprefix_ 
    

    -d 选项用于允许输入行带有尾随空格(与 -L 规范相关)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-18
      • 2011-11-28
      • 2013-06-04
      相关资源
      最近更新 更多