且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

替换多个文件中的多个字符串

更新时间:2023-02-12 20:30:51

给出您到目前为止告诉我们的内容,并考虑注释中所说的所有内容以及问题中涉及的内容以及我能想到的所有可能的字符串目前未包含在您的示例中,但是可能会发生(不包括包含空格的字符串-您必须告诉我们如何在mapfile中识别旧的还是新的来处理),听起来这就是您所需要的:

Given what you've told us so far and considering everything said in comments as well as what's in the question and all of the possible strings I can think of that aren't currently included in your example but can occur (excluding strings that contain spaces - you'd have to tell us how to identify old vs new in mapfile to handle that), it sounds like this is what you need:

$ cat mapfile
Tom Thompson
Billy Bill&Ted
goog1e\.com google.com
https?://www\.google\.com https://google.com

$ cat textfile
Tom and Billy are visiting http://www.goog1e.com

awk '
NR==FNR {
    old[NR] = $1
    gsub(/&/,RS,$2)
    new[NR] = $2
    next
}
{
    for (i=1; i in old; i++) {
        gsub(old[i],new[i])
    }
    gsub(RS,"\\&")
    print
}
' mapfile textfile
Thompson and Bill&Ted are visiting https://google.com

以上内容将旧字符串"视为正则表达式,将新字符串"视为不带反向引用的文字字符串,并严格按照输入文件中定义的顺序应用替换.

The above treats the "old string" as a regexp, treats the "new string" as a literal string with no backreferences and applies the replacements strictly in the order defined in your input file.

第一个gsub()将替换字符串中的每个&转换为一个记录分隔符(由于我们在一条记录内进行操作,因此无法显示),因此第二个gsub()将不会处理&新字符串,例如反向引用,然后第三个gsub()只是将RS放回& s.

The first gsub() converts every & in the replacement string to a Record Separator (which cannot be present since we're operating WITHIN a Record) so that the 2nd gsub() will not treat &s in the new string like a backreference, and then the 3rd gsub() just puts the RSs back to &s.

以上内容可在任何UNIX系统上的任何Shell中使用任何awk进行工作.

The above will work using any awk in any shell on any UNIX system.