使用另一个文件中的第 n 行从两个字符串之间的任何地方替换每个第 n 行

Posted

技术标签:

【中文标题】使用另一个文件中的第 n 行从两个字符串之间的任何地方替换每个第 n 行【英文标题】:Replace each nth occurs from anything between two strings using nth line from another file 【发布时间】:2021-12-21 17:53:01 【问题描述】:

我实际上想使用 nth 行替换 0.txt 文件上的两个字符串之间的任何内容,)\t", 每隔 nth 行从另一个文件 1.txtawk

这类似于Replace each nth occurrence of 'foo' by numerically respective nth line of a supplied file

我一直在寻找一些东西,我试图适应这个https://***.com/a/21876700/10824251,但我不知道它如何适用于我所寻找的东西。这是我的尝试:

awk \

'NR==FNR a[NR]=$0; next /^group_tree(/ /gsub("tortoise", a[++i]) /^)\t",/1' \
    1.txt 0.txt

不要只生成消息的任何结果:

Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
POSIX options:      GNU long options: (standard)
.....

我的源文件:

0.txt:

"#sun\t",
"car_snif = house.group_tree((food, apple,)(bag, tortoise,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((food, apple,)(bag, tortoise,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((food, apple,)(bag, tortoise,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((food, apple,)(bag, tortoise,))\t",
"machine(shoes_shirt.shop)\t",
"#sun\t",
"car_snif = house.group_tree((food, apple,)(bag, tortoise,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((food, apple,)(bag, tortoise,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((food, apple,)(bag, tortoise,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((food, apple,)(bag, tortoise,))\t",

1.txt:

(food, apple,)(bag, tortoise,)
(sky, cat,)(sun, sea,)
(car, shape)(milk, market,)
(man, shirt)(hair, life)
(dog, big)(bal, pink)

我想要的输出2.txt:

"#sun\t",
"car_snif = house.group_tree((food, apple,)(bag, tortoise,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((sky, cat,)(sun, sea,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((car, shape)(milk, market,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((man, shirt)(hair, life))\t",
"machine(shoes_shirt.shop)\t",
"#sun\t",
"car_snif = house.group_tree((dog, big)(bal, pink))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((food, apple,)(bag, tortoise,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((sky, cat,)(sun, sea,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((car, shape)(milk, market,))\t",

【问题讨论】:

您输入中的 \ts 是字面上的 2 个字符 \t 还是您输入中实际上有文字制表符? 在您的问题文本中您说group_tree ( 带有空格,但在您的示例输入/输出中没有这样的空格。请edit您的问题使文本和示例保持一致和正确。 【参考方案1】:

POSIX awk:

awk '
FNR==NR a[i++] = $0
FNR!=NR if (sub(/group_tree[[:space:]]*\(.*\)\\t",$/,
             "group_tree("a[j%i]")\\t\"")) j++
         print' 1.txt 0.txt

您的描述在group_tree( 之间有一个空格,但您的示例数据没有。我允许任何一种情况。

由于两种模式之间存在贪婪的.*,这并不完全可靠。如果您的所有数据都与示例相似,则可能没问题。

请注意,sub(/foo/, a[j++]) 会迭代 j,无论 sub 是否成功。

【讨论】:

我现在正在恢复这个问题的工作,我没有注意到你提到的空间,但我会尝试纠正这个问题,现在你的回复有效,我看看她是如何工作的。 如果1.txt 包含&,那将失败。尝试在1.txt 中将sun, sea 更改为sun & sea @dan 可以解释j%i 的含义,我知道它是一个remaing,但我不确定ji 是否是索引。 @dan 可以让我知道gsub 也可以取代sub【参考方案2】:

您从调用 awk 得到的错误消息是因为您在 awk \ 和脚本之间有一个空行,所以它就像在没有脚本和没有参数的情况下调用 awk。如果你从这里改变它:

awk \

'NR==FNR a[NR]=$0; next /^group_tree(/ /gsub("tortoise", a[++i]) /^)\t",/1' \
    1.txt 0.txt

到这里:

awk \
'NR==FNR a[NR]=$0; next /^group_tree(/ /gsub("tortoise", a[++i]) /^)\t",/1' \
    1.txt 0.txt

或者更习惯的说法是:

awk '
    NR==FNR a[NR]=$0; next /^group_tree(/ /gsub("tortoise", a[++i]) /^)\t",/1
' 1.txt 0.txt

那么您将不会再收到该错误消息(但您将收到不同的错误消息,因为脚本仍然包含语法错误)。

不过,为了解决您的实际问题,使用 GNU awk 作为 match()ARGIND 的第三个参数:

$ cat tst.awk
ARGIND == 1 
    newVals[++totNew] = $0
    next

match($0,/(.*group_tree\().*(\)\\t",.*)/,a) 
    newIdx = ( (++numNew - 1) % totNew ) + 1
    $0 = a[1] newVals[newIdx] a[2]

 print 

$ awk -f tst.awk 1.txt 0.txt
"#sun\t",
"car_snif = house.group_tree((food, apple,)(bag, tortoise,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((sky, cat,)(sun, sea,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((car, shape)(milk, market,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((man, shirt)(hair, life))\t",
"machine(shoes_shirt.shop)\t",
"#sun\t",
"car_snif = house.group_tree((dog, big)(bal, pink))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((food, apple,)(bag, tortoise,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((sky, cat,)(sun, sea,))\t",
"machine(shoes_shirt.shop)\t",
"car_snif = house.group_tree((car, shape)(milk, market,))\t",

以上假设每个group_tree( 后面只有一个)\t",

【讨论】:

你可以解释你的脚本的每一步,执行简单地显示没有错误并且文件2.txt得到0.txt的内容 哪一部分不清楚?我认为它所做的事情的结构是显而易见的,我给了它非常清晰的变量名,所以你知道它们每个的用途,所以我无法想象需要解释什么。 另一个响应的测试更快,因为它已经通过更改两个字符串在第一次尝试和其他测试中工作。我会测试你的更新并尽快给你反馈。 我的解决方案与当前接受的答案之间的主要区别是我使用捕获组,因此我不需要两次指定相同的分隔符字符串,一次在正则表达式中,然后再次在替换中,并且我正在使用 *sub() 进行文字字符串替换而不是启用反向引用的替换,因此无论 1.txt 包含哪些字符,它都会起作用,例如&。我还在测试ARGIND==1 而不是使用NR==FNR,因此您可以将其复制到任何其他文件(我知道您将在后续问题中添加)。不过,我的脚本是 gawk-only。 什么代码使用FNR?我不知道tortoise 是什么,也不知道它与我的答案有什么关系。如果你告诉我答案的哪一部分你不明白,我会解释的。

以上是关于使用另一个文件中的第 n 行从两个字符串之间的任何地方替换每个第 n 行的主要内容,如果未能解决你的问题,请参考以下文章

重命名两个目录中的文件名如果它们之间的某些字符匹配 - 矢量下标超出范围

将行从一个选项卡复制并删除到另一个选项卡

如何将表的行从一个数据库插入另一个数据库(使用两个PDO)

根据 Id [重复] 将行从一个表更新到另一个表

将行从一个表复制到另一个表时如何解决数据截断错误,两个表具有相同的模式?

Numpy - 使用另一个数组的行从一个数组中删除行