Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash-搜索和替换操作,报告更改的文件和行_Bash_Shell_Sed_Find - Fatal编程技术网

Bash-搜索和替换操作,报告更改的文件和行

Bash-搜索和替换操作,报告更改的文件和行,bash,shell,sed,find,Bash,Shell,Sed,Find,我有一个输入文件“test.txt”,如下所示- hostname=abc.com hostname=xyz.com db-host=abc.com db-host=xyz.com 在每一行中,空格前的值是旧值,需要在名为“test”的文件夹中递归地用空格后的新值替换旧值。我可以使用下面的shell脚本来实现这一点 #!/bin/bash IFS=$'\n' for f in `cat test.txt` do OLD=$(echo $f| cut -d ' ' -f 1) ec

我有一个输入文件“test.txt”,如下所示-

hostname=abc.com hostname=xyz.com
db-host=abc.com db-host=xyz.com
在每一行中,空格前的值是旧值,需要在名为“test”的文件夹中递归地用空格后的新值替换旧值。我可以使用下面的shell脚本来实现这一点

#!/bin/bash

IFS=$'\n' 
for f in `cat test.txt`
do
  OLD=$(echo $f| cut -d ' ' -f 1) 
  echo "Old = $OLD"
  NEW=$(echo $f| cut -d ' ' -f 2)
  echo "New = $NEW"
  find test -type f | xargs sed -i.bak "s/$OLD/$NEW/g"
done
“sed”在100个文件中动态替换字符串

是否有一种技巧或替代方法可以让我获得文件更改报告,如文件的绝对路径&更改的确切行数


PS-我知道sed或流编辑器不支持这种开箱即用的功能。我不想使用版本控制,因为这将是一个过度的任务

来自
人力资源

这可用于在替换时创建备份文件。然后,您可以查找任何备份文件,这些文件指示哪些文件已更改,以及
diff
原始文件。检查完差异后,只需删除备份文件


如果您将替换公式化为
sed
语句,而不是自定义格式,则可以进一步使用
sed
shebang行或将文件传递到
-f/--file
,以便在一次操作中完成所有替换。

来自
man-sed

这可用于在替换时创建备份文件。然后,您可以查找任何备份文件,这些文件指示哪些文件已更改,以及
diff
原始文件。检查完差异后,只需删除备份文件


如果您将替换公式化为
sed
语句,而不是自定义格式,则可以进一步使用
sed
shebang行或将文件传递到
-f/--file
在一个操作中执行所有替换操作。

您的脚本有几个问题,只需使用(使用GNU awk代替GNU sed进行就地编辑):


您的脚本有几个问题,只需将其全部替换为(使用GNU awk而不是GNU sed进行就地编辑):


让我们从简单地重写脚本开始,使其在处理更大范围的替换值时更加健壮,但也更快:

#!/bin/bash

# escape regexp and replacement strings for sed
escapeRegex() { sed 's/[^^]/[&]/g; s/\^/\\^/g' <<<"$1"; }
escapeSubst() { sed 's/[&/\]/\\&/g' <<<"$1"; }

while read -r old new; do
    find test -type f -exec sed "/$(escapeRegex "$old")/$(escapeSubst "$new")/g" -i '{}' \;
done <test.txt
上面的
sed
脚本将每个
old
更改为
new
,但它也将
old-->new
行写入
/dev/stdout
(特定于Bash),然后我们将其附加到
change.log
文件中。
find
中的
-printf
操作输出一个“头”带有文件名的行,用于处理的每个文件

这样,您的“更改日志”将如下所示:

[file1]
hostname=abc.com --> hostname=xyz.com

[file2]

[file1]
db-host=abc.com --> db-host=xyz.com

[file2]
db-host=abc.com --> db-host=xyz.com

为了完整起见,快速浏览一下
sed
脚本。我们只对包含
旧值的行进行操作。对于每一行,我们将其存储到保持空间(
h
),将其更改为
新值
,将该新值附加到保持空间(与新行连接,
h
)它现在保存
old\nnew
。我们用模式空间(
x
)交换保留,这样我们可以运行
s
命令,将其转换为
old-->new
。在用
w
将其写入
stdout
后,我们将
new
从保留移回模式空间,这样它就可以被写入(原地)处理的文件。

让我们从简单地重写脚本开始,使其在处理更大范围的替换值时更加健壮,但也更快:

#!/bin/bash

# escape regexp and replacement strings for sed
escapeRegex() { sed 's/[^^]/[&]/g; s/\^/\\^/g' <<<"$1"; }
escapeSubst() { sed 's/[&/\]/\\&/g' <<<"$1"; }

while read -r old new; do
    find test -type f -exec sed "/$(escapeRegex "$old")/$(escapeSubst "$new")/g" -i '{}' \;
done <test.txt
上面的
sed
脚本将每个
old
更改为
new
,但它也将
old-->new
行写入
/dev/stdout
(特定于Bash),然后我们将其附加到
change.log
文件中。
find
中的
-printf
操作输出一个“头”带有文件名的行,用于处理的每个文件

这样,您的“更改日志”将如下所示:

[file1]
hostname=abc.com --> hostname=xyz.com

[file2]

[file1]
db-host=abc.com --> db-host=xyz.com

[file2]
db-host=abc.com --> db-host=xyz.com

为了完整起见,快速浏览一下
sed
脚本。我们只对包含
旧值的行进行操作。对于每一行,我们将其存储到保持空间(
h
),将其更改为
新值
,将该新值附加到保持空间(与新行连接,
h
)它现在保存
old\nnew
。我们用模式空间(
x
)交换保留,这样我们可以运行
s
命令,将其转换为
old-->new
。在用
w
将其写入
stdout
后,我们将
new
从保留移回模式空间,这样它就可以被写入(原地)处理的文件。

好主意,我想了,但是当一个文件中有多个更改时,管理变得复杂。“sed”创建了多个扩展名为1.bak.bak.bak的文件。好主意,我想了,但是当一个文件中有多个更改时,管理变得复杂。“sed”创建多个扩展名为“.bak”的文件,如1.bak.bak.bak。
#!/bin/bash

# escape regexp and replacement strings for sed
escapeRegex() { sed 's/[^^]/[&]/g; s/\^/\\^/g' <<<"$1"; }
escapeSubst() { sed 's/[&/\]/\\&/g' <<<"$1"; }

while read -r old new; do
    find test -type f -printf '\n[%p]\n' -exec sed "/$(escapeRegex "$old")/{
        h
        s//$(escapeSubst "$new")/g
        H
        x
        s/\n/ --> /
        w /dev/stdout
        x
    }" -i '{}' > >(tee -a change.log) \;
done <test.txt
[file1]
hostname=abc.com --> hostname=xyz.com

[file2]

[file1]
db-host=abc.com --> db-host=xyz.com

[file2]
db-host=abc.com --> db-host=xyz.com