逐行替换另一文件中不同文本的部分行

时间:2019-02-01 08:33:55

标签: ubuntu awk sed

我正在尝试解决该问题,但我可以替换整个字符串而不仅仅是部分

这就是我到目前为止所拥有的:

cat mock.txt | sed -i -e '/mock/{R/dev/stdin' -e 'd;}' test{1..500}.txt

我想按顺序从另一个文件中替换与行中的模式匹配的部分,我最多有500个txt文件,其结构为:

test1.txt,test2.txt,test3.txt ...

11111
22222
333= mock 33
55555
77777


所以即时读取文件,并在第一test1.txt文件中将模拟模式替换为来自math.txt文件的第一行,在第二test2.txt中,将模拟模式行替换为来自模拟文件的第二行,具有结构像:

mock.txt

randomText1
randomText2
randomText3
randomText4
randomText5


以此类推,直到文件夹中的最后一个.txt文件

4 个答案:

答案 0 :(得分:1)

对不起,以前的错误,请再试一次。
使用GNU awk v4.1.0 +(请先备份文件):

awk -i inplace 'NR==FNR{re[FNR]=$0;print;next}match(FILENAME,/test([0-9]+)/, fi){gsub("mock",re[fi[1]])}1' mock.txt test{1..500}.txt

请注意,文件不能有回车符\r\n的结尾,如果有的话请发表评论。

如果文件包含多行,则为了提高效率并将其放在几行中以提高可读性:

awk -i inplace '
    NR==FNR{re[FNR]=$0;print;next}
    FNR==1{match(FILENAME,/test([0-9]+)/, fi)}
    /mock/{gsub(/mock/,re[fi[1]])}
    1' mock.txt test{1..500}.txt

答案 1 :(得分:0)

这可能对您有用(GNU sed):

sed -i -e '/mock/R mockFile' -e '//d' file ...

模拟文件在sed脚本中命名,而不是通过stdin输入。这使sed可以为每个输入文件重置模拟文件。

这将用模拟文件中的一行顺序替换mock的所有实例。但是,如果要将每个文件中所有模拟的实例链接到其在模拟文件中的位置,即,将file1中所有模拟的实例链接到模拟文件的第1行等,请使用:

parallel sed -i '/mock/c\{1}' {2} :::: mockFile :::+ file{1..500}.txt

答案 2 :(得分:0)

编辑: :由于OP表示每次文件替换应从模拟文件中模拟字符串的第一次出现开始,因此请立即发布。

awk '
FNR==NR{
  a[FNR]=$0
  next
}
prev!=FILENAME{
  if(prev){
    close("temp")
    system("mv  temp " prev)
  }
}
FNR==1{
  prev=FILENAME
  count=""
}
/mock/{
  $0=a[++count]
}
{
  print > "temp"
}
END{
  if(prev){
    close("temp")
    system("mv  temp " prev)
  }
}' mock.txt test[0-9].txt


能否请您尝试以下。在shost解释中(将添加完整的解释),这将根据模拟文件的值更改字符串模拟值。我添加了一条评论,询问OP关于某个文件是否可以出现1次以上的情况,也将根据OP的回答对其进行更新。

awk '
FNR==NR{
  a[FNR]=$0
  next
}
prev!=FILENAME{
  if(prev){
    close("temp")
    system("mv  temp " prev)
  }
}
FNR==1{
  prev=FILENAME
}
/mock/{
  $0=a[++count]
}
{
  print > "temp"
}
END{
  if(prev){
    close("temp")
    system("mv  temp " prev)
  }
}' mock.txt test[0-9].txt

答案 3 :(得分:0)

您无法通过一步使用sed来完成此操作。

来自info sed

'R filename'
     Queue a line of FILENAME to be read and inserted into the output
     stream at the end of the current cycle, or when the next input line
     is read.

因此,您必须进行第二遍

cd /tmp
seq -f first-%03g 1 20 | tee test-{1..30}.txt >/dev/null 
seq -f newline-%04g 44 244 | sed -i -e '/first-004/R/dev/stdin' test-{1..30}.txt
sed -e '/first-004/{N;s/^\(.*\)rst-00\(.*\)\n\(.*\)/\1\3\2/}' -i test-{1..30}.txt

然后

head -6 test-6.txt
first-001
first-002
first-003
finewline-00494
first-005
first-006

rst-00替换为newline-0049的原位置上的行。

从那里,符合您的请求,但未经过测试:

有两遍:

first-004