如果有方括号,则sed replace无法替换字符串

时间:2019-03-13 13:52:33

标签: sed

我的结果变量包含以下内容:

auth required pam_faillock.so preauth silent audit deny=3 even_deny_root fail_interval=888 unlock_time=888
auth [default=die] pam_faillock.so authfail audit deny=3 even_deny_root fail_interval=888 unlock_time=888

我想替换整行,而我正在使用sed。替换似乎可以在第一次迭代中正常工作,但在第二次迭代中无效。但是,当我打印这些值时,它表明新值已正确更新。

echo "$result" |
   while IFS= read -r line;
   do
      newValue=""
      for ii in $line
      do
         if [[ "$ii" != *"unlock_time"* ]]; then
            newValue="$newValue $ii"
         fi
      done
      newValue="$newValue unlock_time=900"
      sed -i "s/$line/$newValue/g" $password_auth
      echo " Line    : [ $line ]"
      echo "newValue : [ $newValue ]"
   done

输出显示以下内容:

 Line    : [  auth required pam_faillock.so preauth silent audit deny=3 even_deny_root fail_interval=888 unlock_time=900 ]
newValue : [  auth required pam_faillock.so preauth silent audit deny=3 even_deny_root fail_interval=888 unlock_time=900 ]
 Line    : [ auth [default=die] pam_faillock.so authfail audit deny=3 even_deny_root fail_interval=888 unlock_time=888 ]
newValue : [  auth [default=die] pam_faillock.so authfail audit deny=3 even_deny_root fail_interval=888 unlock_time=900 ]

在这里显示时,我看到变量中存在正确的值,并且所有打印都在sed命令之后进行,并且在输出中打印之前我没有看到错误。

但是当我检查文件时,我看到的第二个实例unlock_time仍然是888而不是900。

注意:我无法全局替换unlock_time,这就是为什么我存储需要更新结果的行。

循环中是否有任何被忽略的东西?

更新: 我尝试在命令行上运行sed命令:

sed -i "s/auth required pam_faillock.so preauth silent audit deny=3 even_deny_root fail_interval=888 unlock_time=900/auth required pam_faillock.so preauth silent audit deny=3 even_deny_root fail_interval=888 unlock_time=999/g" temp  <-- This works
sed -i "s/auth [default=die] pam_faillock.so authfail audit deny=3 even_deny_root fail_interval=888 unlock_time=9/auth [default=die] pam_faillock.so authfail audit deny=3 even_deny_root fail_interval=888 unlock_time=900/g" temp   <-- This doesn't update file but doesn't throw an error either

当我在[default = die]周围放置转义字符时,该命令在命令行上有效。但是,如果我通过脚本来执行该操作呢?

1 个答案:

答案 0 :(得分:1)

您正试图找到一个常数。通过多层报价进行正则表达式匹配的方式越来越麻烦。这是一个更简单的perl方法(出于演示目的,打包在bash中):

#!/bin/bash

result="auth required pam_faillock.so preauth silent audit deny=3 even_deny_root fail_interval=888 unlock_time=888
auth [default=die] pam_faillock.so authfail audit deny=3 even_deny_root fail_interval=888 unlock_time=888"

# create a file to play with
echo "$result" > testfile

echo "$result" | perl -i -pe '
    BEGIN { @find = <STDIN> }
    for $str (@find) {
        s/(\bunlock_time)=\d+/$1=900/ if $_ eq $str;
    }
' testfile

# check the result
cat testfile
  • -i像sed一样进行就地编辑
  • -p包装while循环以读取每一行,因此不需要显式的行,并在可能的修改(有点像sed)后打印出该行
  • BEGIN部分初始化要从(结果中)查找的字符串数组
  • 对于测试文件($_)的每一行,for将其与所有字符串进行比较,并且if存在文字匹配(eq),进行正则表达式搜索并替换unlock_time参数