如何检查sed是否更改了文件

bre*_*986 15 linux bash shell ubuntu sed

我试图找到一种聪明的方法来确定传递给sed的文件是否已成功更改.

基本上,我想知道文件是否已被更改,而不必查看文件修改日期.

我需要这个的原因是因为如果sed成功替换了模式,我需要做一些额外的事情.

我目前有:

    grep -q $pattern $filename
    if [ $? -eq 0 ]
    then
        sed -i s:$pattern:$new_pattern: $filename
                # DO SOME OTHER STUFF HERE
    else
        # DO SOME OTHER STUFF HERE
    fi
Run Code Online (Sandbox Code Playgroud)

上面的代码有点贵,我希望能在这里使用一些黑客.

aur*_*vel 23

派对有点晚了但是为了别人的利益,我发现'w'标志正是我想要的.

sed -i "s/$pattern/$new_pattern/w changelog.txt" "$filename"
if [ -s changelog.txt ]; then
    # CHANGES MADE, DO SOME STUFF HERE
else
    # NO CHANGES MADE, DO SOME OTHER STUFF HERE
fi
Run Code Online (Sandbox Code Playgroud)

changelog.txt将包含每个更改(即更改的文本)在它自己的行上.如果没有变化,changelog.txt则为零字节.

一个非常有用的sed资源(我在哪里找到这个信息)是http://www.grymoire.com/Unix/Sed.html.

  • 也适用于 `s/search/replace/ w /dev/stdout` - 无需创建临时文件:) 请参阅 [acecilia 的解决方案](/sf/answers/4326585511/) (4认同)
  • 我发现覆盖很方便...在每次`sed`之后我可以检查而不必记住删除文件。 (2认同)
  • @pgr`sed -i“s/a/b/gw /dev/stdout”文件` (2认同)

hos*_*ter 10

我相信你可能会发现这些GNU sed扩展很有用

t label

If a s/// has done a successful substitution since the last input line
was read and since the last t or T command, then branch to label; if
label is omitted, branch to end of script.
Run Code Online (Sandbox Code Playgroud)

q [exit-code]

Immediately quit the sed script without processing any more input, except 
that if auto-print is not disabled the current pattern space will be printed. 
The exit code argument is a GNU extension.
Run Code Online (Sandbox Code Playgroud)

看起来你正在寻找什么.

  • 我不明白如何使用它 (20认同)
  • 重要提示:看起来这仅适用于单行模式。对于 sed-ing 整个文件,替换是在中间的某个地方完成的,在 sed 解析第一行并且在那里找不到替换后,它将只打印第一行不变并退出。 (4认同)
  • 如何将“t”和“q”选项与“sed”命令一起使用,解释如下:https://askubuntu.com/a/1036918/250399。TLDR:`sed -i 's/orig/repl/; t; q1' 文件.txt` (3认同)

pot*_*ong 7

这可能适合你(GNU sed):

sed -i.bak '/'"$old_pattern"'/{s//'"$new_pattern"'/;h};${x;/./{x;q1};x}' file || echo changed
Run Code Online (Sandbox Code Playgroud)

说明:

  • /'"$old_pattern"'/{s//'"$new_pattern"'/;h}如果图案空间(PS)包含old pattern,则将其替换为new pattern并将PS复制到保持空间(HS).
  • ${x;/./{x;q1};x}在遇到最后一行时,交换到HS并测试它是否存在任何字符串.如果在HS中找到一个字符串(即已发生替换),则交换回原始PS并使用退出代码退出1,否则切换回原始PS并退出,退出代码为0(默认值).


Wil*_*ell 6

你可以awk改用:

awk "/$pattern/"' { gsub( "'"$pattern"'", "'"$repl"'" ); t=1 }
    1; END{ exit( !t )}'
Run Code Online (Sandbox Code Playgroud)

我忽略了这个-i功能:你可以根据需要使用shell做重定向.

  • 您不能仅使用shell重定向进行就地修改.命令文件>文件不起作用(文件在应用重定向时被截断,这在命令启动之前发生) (3认同)
  • 你能用awk给出一个完整的解决方案吗?你不清楚你忽略-i特征或sed与此有什么关系是什么意思.您的代码似乎不起作用 (2认同)

per*_*eal 5

您可以将原始文件与 sed 输出进行比较,以查看它是否已更改:

sed -i.bak s:$pattern:$new_pattern: "$filename"
if ! diff "$filename" "$filename.bak" &> /dev/null; then
  echo "changed"
else
  echo "not changed"
fi
rm "$filename.bak"
Run Code Online (Sandbox Code Playgroud)

  • `diff` 向您展示了不同之处。如果您只是想知道是否有任何区别,`cmp` 就足够了。还有`[ $? -ne 0]` 没用。只需将命令放入 `if` 条件: `if cmp "$filename" "$filename".bak; 然后`。 (3认同)
  • `diff` 会比他试图替换的 `grep` 便宜吗? (2认同)

ace*_*lia 5

在macos中我只是这样做:

changes=""
changes+=$(sed -i '' "s/$to_replace/$replacement/g w /dev/stdout" "$f")
if [ "$changes" != "" ]; then
  echo "CHANGED!"
fi
Run Code Online (Sandbox Code Playgroud)

我查了一下,这比md5cksum比较sha