替换没有正则表达式的字符串

Geo*_*rge 1 unix shell scripting awk sed

我希望有一个shell脚本来执行查找和替换,而不使用正则表达式(正则表达式),其中包括所有特殊字符,如!@#$%¨&*()?^〜]} [{' `> <","

因此,例如,函数将能够接收两个参数,其中第一个将是我想要找到的,第二个参数将被替换为.

例1:

File1:
BETWEEN TO_DATE('&1','YYYY-MM-DD') +1  and TO_DATE('&2','YYYY-MM-DD') +15

First parameter: TO_DATE('&1','YYYY-MM-DD') 
Second parameter: TO_DATE('&1 23:59:59','YYYY-MM-DD HH@$:MI:SS') 

File1 after calling the function to replace:

BETWEEN TO_DATE('&1 23:59:59','YYYY-MM-DD HH@$:MI:SS')  +1  and TO_DATE('&2','YYYY-MM-DD') +15
Run Code Online (Sandbox Code Playgroud)

例2:

File2:
This is just a test/2^

Paramter1: test/2^
Paramter1: testing\$2^]'

File2 after calling the function to replace:
This is just a test/2^
Run Code Online (Sandbox Code Playgroud)

param1和param2可以是任何东西.

我需要使用UNIX OS AIX,它可以是使用sed或awk的KornShell(ksh).我不能使用perl或Java.我也无法在这台服务器上安装任何东西.

gle*_*man 7

我使用awk和不使用模式的字符串函数index()和substr()

awk -v find="$param1" -v repl="$param2" '{
    while (i=index($0,find)) 
        $0 = substr($0,1,i-1) repl substr($0,i+length(find))
    print
}' file
Run Code Online (Sandbox Code Playgroud)

我假设每行可能有多个匹配.


测试

$ param1="TO_DATE('&1','YYYY-MM-DD')"
$ param2="TO_DATE('&1 23:59:59','YYYY-MM-DD HH@$:MI:SS')"
$ awk -v find="$param1" -v repl="$param2" '{
    while (i=index($0,find)) 
        $0 = substr($0,1,i-1) repl substr($0,i+length(find))
    print
}' << END
BETWEEN TO_DATE('&1','YYYY-MM-DD') +1  and TO_DATE('&2','YYYY-MM-DD') +15
END
Run Code Online (Sandbox Code Playgroud)
BETWEEN TO_DATE('&1 23:59:59','YYYY-MM-DD HH@$:MI:SS') +1  and TO_DATE('&2','YYYY-MM-DD') +15
Run Code Online (Sandbox Code Playgroud)

第二次测试有点问题:

$ param1='test/2^'
$ param2='testing\$2^]'\'
$ awk -v find="$param1" -v repl="$param2" '{
    while (i=index($0,find)) 
        $0 = substr($0,1,i-1) repl substr($0,i+length(find))
    print
}' <<< "This is just a test/2^"
Run Code Online (Sandbox Code Playgroud)
awk: warning: escape sequence `\$' treated as plain `$'
This is just a testing$2^]'
Run Code Online (Sandbox Code Playgroud)

因此,您需要预处理参数以转义任何反斜杠:

$ awk -v find="$(sed 's/\\/&&/g' <<< "$param1")" \
      -v repl="$(sed 's/\\/&&/g' <<< "$param2")" \
'{
    while (i=index($0,find)) 
        $0 = substr($0,1,i-1) repl substr($0,i+length(find))
    print
}' <<< "This is just a test/2^"
Run Code Online (Sandbox Code Playgroud)
This is just a testing\$2^]'
Run Code Online (Sandbox Code Playgroud)

为了适应Ed的精明点:

param1=foo
param2=_foo_
awk -v find="$(sed 's/\\/&&/g' <<< "$param1")" \
    -v repl="$(sed 's/\\/&&/g' <<< "$param2")" \
'
    index($0, find) {
        start = 1
        line = $0
        newline = ""
        while (i=index(line, find)) {
            newline = newline substr(line, 1, i-1) repl
            start += i + length(find) - 1
            line = substr($0, start)
        }
        $0 = newline line
    }
    {print}
' <<END
abcfoodeffooghifoobar
food
blahfoo
no match
END
Run Code Online (Sandbox Code Playgroud)
abc_foo_def_foo_ghi_foo_bar
_foo_d
blah_foo_
no match
Run Code Online (Sandbox Code Playgroud)

  • 你实际上不应该使用那种方法,因为`repl`字符串可能包含`find`字符串,然后你会陷入无限循环.你需要首先在当前记录中找到`find`的每一个出现,然后用`repl`s替换它们. (3认同)