了解 sed 中关于保存的 !d 命令

了解 sed 中关于保存的 !d 命令

我有一个包含制表符分隔文本文件的目录,其中一些文件的前几行包含注释,我想删除这些注释。我知道第一行以“Mark”开头,这样我就可以用来/^Mark/,$!d删除这些注释。删除之后,我在(新的)第一行中进行了其他几处替换,这些替换包含变量名。

我的问题是,为什么我必须保存sed的输出才能使我的脚本正常工作?我理解如果删除 I 行,则输出不会继续进行,因为没有输出。但如果我删除(即!d),那么为什么我必须保存到文件?谢谢!

这是我的 shell 脚本。(我是sed新手,因此也欢迎任何其他反馈。)

#!/bin/bash
for file in *.txt; do
    mv $file $file.old1
    sed -e '/^Mark/,$!d' $file.old1 > $file.old2
    sed -e '1s/\([Ss]\)hareholder/\1hrhldr/g'\
        -e '1s/\([Ii]\)mmediate/\1mmdt/g'\
        -e '1s/\([Nn]\)umber/\1o/g'\
        -e '1s/\([Cc]\)ompany/\1o/g'\
        -e '1s/\([Ii]\)nformation/\1nfo/g'\
        -e '1s/\([Pp]\)ercentage/\1ct/g'\
        -e '1s/\([Dd]\)omestic/\1om/g'\
        -e '1s/\([Gg]\)lobal/\1lbl/g'\
        -e '1s/\([Cc]\)ountry/\1ntry/g'\
        -e '1s/\([Ss]\)ource/\1rc/g'\
        -e '1s/\([Oo]\)wnership/\1wnrshp/g'\
        -e '1s/\([Uu]\)ltimate/\1ltmt/g'\
        -e '1s/\([Ii]\)ncorporation/\1ncorp/g'\
        -e '1s/\([Tt]\)otal/\1ot/g'\
        -e '1s/\([Dd]\)irect/\1ir/g'\
        $file.old2 > $file
        rm -f $file.old*
done

答案1

使用sponge可能是覆盖输入文件的最安全方法。sponge正确处理与文件相关的链接,sed -i但不能。请参阅此链接:有没有办法就地修改文件?

测试文件

echo "comment
comment
Mark Global Ownership
Shareholder
Domestic
Last line" >test.txt
file=test.txt
cat "$file"
echo =====

没有循环的脚本..(只需添加循环)

sed -n '/^Mark/,${  # check for "first time"
          G         # append the hold space, looking for "\nX" 
          /\n$/{    # nothing in the hold space, so "first time"
            s/\n$// # remove \n introduced by G
            s/\([Ss]\)hareholder/\1hrhldr/g
            s/\([Ii]\)mmediate/\1mmdt/g
            s/\([Nn]\)umber/\1o/g
            s/\([Cc]\)ompany/\1o/g
            s/\([Ii]\)nformation/\1nfo/g
            s/\([Pp]\)ercentage/\1ct/g
            s/\([Dd]\)omestic/\1om/g
            s/\([Gg]\)lobal/\1lbl/g
            s/\([Cc]\)ountry/\1ntry/g
            s/\([Ss]\)ource/\1rc/g
            s/\([Oo]\)wnership/\1wnrshp/g
            s/\([Uu]\)ltimate/\1ltmt/g
            s/\([Ii]\)ncorporation/\1ncorp/g
            s/\([Tt]\)otal/\1ot/g
            s/\([Dd]\)irect/\1ir/g
            p           # print
            s/.*/X/; h  # set a "flag" in the hold space 
            b           # branch unconditionally (ie, next)
          };
          P;b   # print line (before "\nX") and branch            
        };d' "$file" | sponge "$file"

cat "$file"

输出

comment
comment
Mark Global Ownership
Shareholder
Domestic
Last line
=====
Mark Glbl Ownrshp
Shareholder
Domestic
Last line

答案2

没有必要将标准输出保存到文件。您可以将|输出通过管道()传输到下一个sed进程。其他选项是使用 的sed选项edit in place-i

男人

-i[SUFFIX], --in-place[=SUFFIX]
    edit files in place (makes backup if extension supplied) 

相关内容