使用 sed 编辑匹配模式的任何一个出现

Daz*_*Jay 6 command-line sed text-processing

以 Fred Flintstone开头的行应附加一些字符串。?查找指定出现的 Fred Flintstone 并将其附加。

对于出现这种模式的任何人,我如何使用此命令?我试过

sed '/Fred Flintstone/ s/$/ someString/2' filename
Run Code Online (Sandbox Code Playgroud)

显然上面的一个不起作用。它适用于所有事件,但不适用于特定事件。(假设我想替换第一个或第二个或第三个 [其中任何一个])

示例文件 1:

Fred Flintstone 
Johnson Stone
Fred Flintstone
Fred Flintstone
Michael Clark
Run Code Online (Sandbox Code Playgroud)

所需的输出文件 1:

Fred Flintstone 
Johnson Stone
Fred Flintstone someString
Fred Flintstone
Michael Clark
Run Code Online (Sandbox Code Playgroud)

hee*_*ayl 7

尽管您已经提到过sed,但这些都是awk-y 任务:

awk -v pat="Fred Flintstone" '$0 ~ pat {count++;\
               if (count == 2) { $0 = $0" someString" ;} ;}; 1' file.txt
Run Code Online (Sandbox Code Playgroud)
  • -v pat="Fred Flintstone"保存 Regex 模式以匹配为pat要在awk表达式中使用的变量

  • $0 ~ pat检查记录pat是否匹配;如果匹配,则count变量增加 1,如果count是 2,则记录将重置为当前内容加上someString( {count++; if (count == 2) { $0 = $0" someString" ;} ;})

  • 1是成语;因为它是真实的,所有的记录都会被打印出来

例子:

% cat file.txt
Fred Flintstone
Johnson Stone
Fred Flintstone
Fred Flintstone
Michael Clark

% awk -v pat="Fred Flintstone" '$0 ~ pat {count++; if (count == 2) { $0 = $0" someString" ;} ;}; 1' file.txt
Fred Flintstone
Johnson Stone
Fred Flintstone someString
Fred Flintstone
Michael Clark
Run Code Online (Sandbox Code Playgroud)


αғs*_*нιη 5

修改答案以防止在使用awk变量awk -v variable ...或 shell时在反斜杠以及斜杠、引号上注入代码,awk '...' variable="$value"因为awk对通过-v variable=或 shell传递的值进行 C 转义序列处理variable=$value;因此外壳variable='\\n'将更改为\nawk内)。

pattern="${patt//\\/\\\\}" awk '
    $0 ~ ENVIRON["pattern"]{ seen++ } seen==2 { $0 = $0 "something"};1' infile
Run Code Online (Sandbox Code Playgroud)

对于以下输入和模式

another break line
Johnson Stone
\"Fred //\\Flintstone' SOMETHING will goes here ...
\"Fred //\\Flintstone'
Michael Clark
Run Code Online (Sandbox Code Playgroud)

模式在一个名为的变量中 patt

$ echo "$patt"
\"Fred //\\Flintstone'
Run Code Online (Sandbox Code Playgroud)

输出是:

\"Fred //\\Flintstone'
another break line
Johnson Stone
\"Fred //\\Flintstone' SOMETHING will goes here ...something
\"Fred //\\Flintstone'
Michael Clark
Run Code Online (Sandbox Code Playgroud)

解释:

稍后您可能需要将something字符串作为变量传递,并且您将需要使用类似的东西edit=$somestingENVIRON["edit"]在那里使用。

pattern="${patt//\\/\\\\}" edit="$something" awk '
    $0 ~ ENVIRON["pattern"]{ seen++ } seen==2 { $0 = $0 ENVIRON["edit"]};1' infile
Run Code Online (Sandbox Code Playgroud)


Den*_*son 5

这个简单的sed命令允许您在不使用循环(它确实使用分支到结束)或不需要 GNU 扩展或一次读取整个文件的情况下有选择地进行更改:

sed -r '/Fred Flintstone/ {x; s/$/#/; /^#{2}$/ {x; s/.*/& someString/; b}; x}'
Run Code Online (Sandbox Code Playgroud)

解释:

  • -r - 使用扩展的正则表达式
  • /Fred Flintstone/ - 对于匹配此模式的行:
    • x - 交换模式空间和保持空间(激活计数器)
    • s/$/#/ - 向计数器添加一个字符
    • /^#{2}$/ - 当计数器长度为 2 时(替换任何值)
      • x 交换模式空间和保持空间(激活计数输入行)
      • s/.*/& someString/ - 将字符串附加到所需的行
      • b - 跳到这一行的处理结束,以便可以打印
    • x - 交换模式空间并保持空间(激活匹配字符串但不匹配计数的行)

解释中的缩进级别表示花括号嵌套的级别。

所有其他行无需处理即可通过并打印。