通过使用带有 SED 的行号列表在某些行中附加单词

通过使用带有 SED 的行号列表在某些行中附加单词

我有一个文件 example.txt,其中包含多行:

Larry is funny!
Funny, I've no glue!
Look here!
Tom has no pants.
The underpants are in the drawer.
Pants are in the closet!

创建具有 4 个随机行号的文件后

sed -n '=' example.txt | shuf | head -3 > line_numbers.txt

假设 line_numbers.txt 中的行号包含

1
3
6

我想通过在 line_numbers.txt 的每一行附加单词 WORD 来编辑 example.txt,其中包含完整的单词“pants”(而不是像“underpants”这样的部分单词)。

我怎样才能做到这一点?

我希望 example.txt 看起来像这样

Larry is funny!
Funny, I've no glue!
Look here!
Tom has no pants.
The underpants are in the drawer.
Pants are in the closet!WORD

编辑:

要仅查找完整单词,您必须像这样编写您的 source_word \<source_word\>

其他可能的例子:

我有另一个文件包含这些行:

I love apples.
You hate pineapples.
Apple pie is delicious.
Why do you do not like eating an apple?
We prefer pears to apples.
How many apples do you want to eat?
I have to bake three apple pies for sunday.

我有一个包含三个随机行号的列表

6
2
4

我只想在每行末尾添加--OK(如果该行包含完整的单词)apples

输出必须如下所示:

I love apples.
You hate pineapples.
Apple pie is delicious.
Why do you do not like eating an apple?
We prefer pears to apples.
How many apples do you want to eat?--OK
I have to bake three apple pies for sunday.

答案1

我希望也有办法sed,但就我个人而言,我发现awk这种更复杂的操作要容易得多:

awk 'NR==FNR{a[$1]++; next} 
    { 
        s=tolower($0); 
        if(FNR in a && s~/pants/){$0=$0"WORD"}
    }1' line_numbers.txt examples.txt 
Larry is funny!
Funny, I've no glue!
Look here!
Tom has no pants.
The underpants are in the drawer.
Pants are in the closet!WORD

如果您有 GNU awkgawkLinux 系统上的默认设置),您可以执行以下操作来就地编辑文件:

gawk -i inplace 'NR==FNR{a[$1]++; print; next} 
                { 
                    s=tolower($0); 
                    if(FNR in a && s~/pants/){$0=$0"WORD"}
                }1' line_numbers.txt examples.txt 

或者,如果您不介意丢失以下内容,则稍微简单一些line_numbers.txt

gawk -i inplace 'NR==FNR{a[$1]++; next} 
                { 
                    s=tolower($0); 
                    if(FNR in a && s~/pants/){$0=$0"WORD"}
                }1' line_numbers.txt examples.txt 

答案2

以下管道是您的修改版,输出sed执行您编辑的脚本:

sed -n '=' file | shuf -n 3 | sed 's,$, { /\\<pants\\>/ s/$/WORD/; },'

或者,等价地,

awk '{ printf "%d { /\\<pants\\>/ s/$/WORD/; }\n", NR }' file | shuf -n 3

例如,这可以生成

6 { /\<pants\>/ s/$/WORD/; }
5 { /\<pants\>/ s/$/WORD/; }
1 { /\<pants\>/ s/$/WORD/; }

如果该模式出现在任何随机选择的行上,则此脚本会应用替换,该替换会WORD在与模式匹配的每行末尾添加。pants

运行它只需使用以下命令读取它sed -f

sed -n '=' example.txt | shuf -n 3 | sed 's,$, { /\\<pants\\>/ s/$/WORD/; },' |
sed -i -f /dev/stdin example.txt

或者,使用基于我的awk变体:

awk '{ printf "%d { /\\<pants\\>/ s/$/WORD/; }\n", NR }' example.txt | shuf -n 3 |
sed -i -f /dev/stdin example.txt

不需要中间文件。

替换pantsapplesWORDwith--OK以解决您更新的查询。

答案3

这是一个单行(虽然有点长!)。

假设你的文本文件是“tfile”,索引文件是ifile,那么:

awk 'BEGIN{i=0;p=0}{if(FNR==NR){a[i++]=$1} else {if(a[p]==FNR){p++;g="";if(index($0,"Pants")){g="WORD"};  print $0,g}else{print $0}}}' ifile tfile

你会得到:

Larry is funny! 
Funny, I've no glue!
Look here! 
Tom has no pants.
The underpants are in the drawer.
Pants are in the closet! WORD 

答案4

使用 GNU sed,我们可以从行号文件构造 sed 代码并将它们应用到数据文件上:

sed -f - <<\eof line_numbers.txt |\
sed -f - example.txt
  1i /pants/I!b
  s/$/ba/
  $a b;:a;s/$/WORD/
eof

另一种方法是我们按行号转录 sed 命令

sed -e 's:.*:&s/pants.*/\&WORD/I;t:' line_numbers.txt |
sed -f /dev/stdin example.txt

相关内容