Bash脚本来replace文件,如果它有一个特定的string

我有一个文件列表,我想检查一个特定的string。 如果string存在于文件中,我想用新版本replace它。 什么是最简单的方法呢?

for file in "`grep -l "foo" bar gazi`"; do cp -p --backup=numbered replace "$file"; done 

replace是replace文件的path, bargazi表示要检查的文件列表,而foo是感兴趣的searchstring。

如果你需要额外的帮助,为grep(上面)制定一个适当的正则expression式,请不要犹豫,问。

grep可以search一个string的文件,如果发现它会返回0,你可以用它作为条件的一部分来replace文件,如下所示:

  #!/bin/bash if [ !`/bin/grep -q teststring /path/to/file` ]; then cp newfile oldfile fi 

大概你有一个文件列表中的文件? 我不知道你是否有一个静态文件,你正在replace匹配的文件,或每个文件的潜在替代品。 这处理第二种情况,第一种情况下,只是用静态文件名replace$ i.new。

 for i in `cat /var/tmp/listoffiles` ; do if grep string $i > /dev/null 2>&1 ; then cp $i $i.old cp $i.new $i fi done 

虽然我同意所有的greptesting,但是sed可以在没有testing的情况下做到这一点。

sed -i.BACKUP's / STRING您想要更换/ NEW STRING /'文件

如果string不在那里,它不会做任何事情。 值得一提的是 从你的问题,我不知道你是否试图更换整个文件或只是一个string。

在shell脚本中循环处理文件的正确方法是将命令放入while或将文件redirect到while循环的done语句。 这将处理除包含换行符之外的任何名称。 你不应该for f in $(cmd)使用for f in $(cmd)的forms。

在这个例子中, find是产生文件列表的命令:

 find . -type f -name "*.txt" | while read -r filename do if grep -qs "$string" "$filename" # or use >/dev/null 2>&1 instead of -qs then cp "$replacement" "$filename" fi done 

或者,这里列表包含在一个文件中:

 while read -r filename ... done < "$file_with_list" 

另一种方法是使用xargs

对于生成文件列表的命令(例如find ):

 find . -type f -name "*.txt" -print0 | xargs -0 -I % env string=$string sh 'grep -qs "$string" "%" && cp replacement_file "%"' 

前面的方法在文件名可能包含换行符的情况下工作。

如果列表在一个文件中:

 xargs -a "$file_with_list" -I % env string=$string sh 'grep -qs "$string" "%" && cp replacement "%"' 

所有这些例子都适用于文件名可能包含空格的情况。