string - 将两个不同列上第 n 次出现的 'foo' 和 'bar' 替换为相应列中所提供文件的第 n 行的数字

标签 string awk replace gsub text-processing

我有一个 source.txt如下包含两列数据的文件。 source.txt 的列格式包括[ ] (方括号),如我的 source.txt 所示:

[hot] [water]
[16] [boots and, juice]

我还有一个 target.txt文件并包含空行加上每行末尾的句点:

the weather is today (foo) but we still have (bar). 

= (

the next bus leaves at (foo) pm, we can't forget to take the (bar).

我想替换 foo target.txt 的第 n 行与source.txt第一列的“各自的内容” , 并替换 bar target.txt 的第 n 行与source. txt第二列的“各自的内容” .

我尝试搜索其他来源并了解我将如何做,起初我已经有一个命令可以用来替换 "replace each nth occurrence of 'foo' by numerically respective nth line of a supplied file"但我无法适应它:

awk 'NR==FNR {a[NR]=$0; next} /foo/{gsub("foo", a[++i])} 1' source.txt target.txt > output.txt;

我记得看到过一种使用包含两列数据的 gsub 的方法,但我不记得究竟有什么区别。

EDIT POST:有时阅读时会在它们之间加上一些符号 =()在 target.txt 文本中。我添加了这个符号,因为如果这些符号在 target.txt 中,一些答案将不起作用。文件

注:target.txt的个数|行,因此出现的次数 barfoo在这个文件中可能会有所不同,我只是展示了一个示例。但是两者的出现次数 foobar每行分别为1。

最佳答案

使用您展示的示例,请尝试以下答案。用 GNU awk 编写和测试。

awk -F'\\[|\\] \\[|\\]' '
FNR==NR{
  foo[FNR]=$2
  bar[FNR]=$3
  next
}
NF{
  gsub(/\<foo\>/,foo[++count])
  gsub(/\<bar\>/,bar[count])
}
1
' source.txt FS=" " target.txt

说明: 为以上添加详细说明。

awk -F'\\[|\\] \\[|\\]' '       ##Setting field separator as [ OR ] [ OR ] here.
FNR==NR{                        ##Checking condition FNR==NR which will be TRUE when source.txt will be read.
  foo[FNR]=$2                   ##Creating foo array with index of FNR and value of 2nd field here.   
  bar[FNR]=$3                   ##Creating bar array with index of FNR and value of 3rd field here.
  next                          ##next will skip all further statements from here.
}
NF{                             ##If line is NOT empty then do following.
  gsub(/\<foo\>/,foo[++count])  ##Globally substituting foo with array foo value, whose index is count.
  gsub(/\<bar\>/,bar[count])    ##Globally substituting bar with array of bar with index of count.
}
1                               ##printing line here.
' source.txt FS=" " target.txt  ##Mentioning Input_files names here.


编辑: 还添加以下解决方案,它将处理源中出现 n 次 [...] 并在目标中匹配它们文件也。因为这是 OP 的工作解决方案(在评论中确认),所以在此处添加。当 source.txt 包含 & 时,也公平警告这将失败。

awk '
FNR==NR{
  while(match($0,/\[[^]]*\]/)){
    arr[++count]=substr($0,RSTART+1,RLENGTH-2)
    $0=substr($0,RSTART+RLENGTH)
  }
  next
}
{
  line=$0
  while(match(line,/\(?[[:space:]]*(\<foo\>|\<bar\>)[[:space:]]*\)?/)){
    val=substr(line,RSTART,RLENGTH)
    sub(val,arr[++count1])
    line=substr(line,RSTART+RLENGTH)
  }
}
1
' source.txt target.txt

关于string - 将两个不同列上第 n 次出现的 'foo' 和 'bar' 替换为相应列中所提供文件的第 n 行的数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68702193/

相关文章:

linux - 计算文本文件中的一致性和相关性

python - python3中的多个替换值

Java用未知索引替换arraylist中的对象

javascript - 比较两个字符串并返回它们之间的共同字符?

python - 从 numpy.int32 数组的数据字节中有效地删除每 4 个字节

bash - tail -f、awk 并输出到文件 >

javascript - Jquery 在封闭的 CMS 中围绕 html 添加 div

java - 如何在 Java 中操作返回字符串的值

php - 自动更改空格和下划线

bash - 删除文件 A 中包含文件 B 中字符串的所有行