Bash - 搜索和替换操作,报告已更改的文件和行 [英] Bash - Search and Replace operation with reporting the files and lines that got changed
问题描述
我有一个输入文件test.txt,如下所示:
I have a input file "test.txt" as below -
hostname=abc.com hostname=xyz.com
db-host=abc.com db-host=xyz.com
,space之前的值是在名为test的文件夹中递归地递归之后需要用新值替换的旧值。
In each line, the value before space is the old value which needs to be replaced by the new value after the space recursively in a folder named "test". I am able to do this using below shell script.
#!/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在100s的文件中替换字符串。
"sed" replaces the strings on the fly in 100s of files.
是否有一个技巧或替代方式,我可以得到一个文件的变化报告文件的绝对路径确切的线条得到了改变?
Is there a trick or an alternative way by which i can get a report of the files changed like absolute path of the file & the exact lines that got changed ?
我知道sed或流编辑器不支持这个功能。我不想使用版本控制,因为这对于这个任务来说是一个矫枉过正的事情。
PS - I understand that sed or stream editors doesn't support this functionality out of the box. I don't want to use versioning as it will be an overkill for this task.
推荐答案
让我们从简单的脚本重写入手,让它在处理更广泛的替换值,但也更快:
Let's start with a simple rewrite of your script, to make it a little bit more robust at handling a wider range of replacement values, but also faster:
#!/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
所以,我们循环了一对空格分隔的字段( old
, new
)从 test.txt
并对所有使用 find
找到的文件执行标准的 sed
替换。
So, we loop over pairs of whitespace-separated fields (old
, new
) in lines from test.txt
and run a standard sed
in-place replace on all files found with find
.
非常类似于您的脚本,但我们正确阅读 test.txt
(不分词,路径名/变量扩展等),我们尽可能使用Bash内建函数(不需要调用外部工具,如 cat
, cut
, xargs
);我们转义 sed code> old
/ new
的code>元字符作为 sed
的正则表达式和替换表达式。
Pretty similar to your script, but we properly read lines from test.txt
(no word splitting, pathname/variable expansion, etc.), we use Bash builtins whenever possible (no need to call external tools like cat
, cut
, xargs
); and we escape sed
metacharacters in old
/new
values for proper use as sed
's regexp and replacement expressions.
现在我们添加从sed登录:
Now let's add logging from 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 -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
sed $上面的c $ c>脚本将每个
旧的
改为新的
,但是它也写入 - >新的
行到 / dev / stdout
(Bash特定的),我们依次追加到 change.log
文件。
find
中的 -printf
操作为每个处理过的文件输出一个带有文件名的header行。
The sed
script above changes each old
to new
, but it also writes old --> new
line to /dev/stdout
(Bash-specific), which we in turn append to change.log
file. The -printf
action in find
outputs a "header" line with file name, for each file processed.
有了这个,你的更改日志就会变成这样:
With this, your "change log" will look something like:
[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
),将其更改为 new
,追加新值到现在持有 old \\\
的保留空间(以换行符连接,
new H
)。我们用模式空间( x
)交换保持,所以我们可以运行 s
命令将其转换为旧 - >新
。在用 w
写入 stdout
之后,我们将 new
从保存到模式空间,所以它被写入(到位)到处理的文件。
Just for completeness, a quick walk-through the sed
script. We act only on lines containing the old
value. For each such line, we store it to hold space (h
), change it to new
, append that new value to the hold space (joined with newline, H
) which now holds old\nnew
. We swap hold with pattern space (x
), so we can run s
command that converts it to old --> new
. After writing that to the stdout
with w
, we move the new
back from hold to pattern space, so it gets written (in-place) to the file processed.
这篇关于Bash - 搜索和替换操作,报告已更改的文件和行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!