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)
尽管您已经提到过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)
修改答案以防止在使用awk变量awk -v variable ...或 shell时在反斜杠以及斜杠、引号上注入代码,awk '...' variable="$value"因为awk对通过-v variable=或 shell传递的值进行 C 转义序列处理variable=$value;因此外壳variable='\\n'将更改为\n在awk内)。
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)
这会pattern="${patt//\\/\\\\}"转义$patt变量中的所有反斜杠,因为 [ " the '~' operator does pattern matching, treating the right hand operand as an (extended) regular expression, and the left hand one as a string" by muru ],那么您将需要转义ERE 中的所有特殊字符。
这会$0 ~ ENVIRON["pattern"]{ seen++ }检查当前行是否与 匹配pattern,然后将值增加seen++一次。
这会seen==2 { $0 = $0 "something"}'检查是否有第二行与pattern上面的结果(现在seen==2)匹配,然后在该行的末尾附加字符串“somestring”。
最后的1(或任何 True 语句)启用awk默认打印。
稍后您可能需要将something字符串作为变量传递,并且您将需要使用类似的东西edit=$somesting并ENVIRON["edit"]在那里使用。
pattern="${patt//\\/\\\\}" edit="$something" awk '
$0 ~ ENVIRON["pattern"]{ seen++ } seen==2 { $0 = $0 ENVIRON["edit"]};1' infile
Run Code Online (Sandbox Code Playgroud)
这个简单的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 - 交换模式空间并保持空间(激活匹配字符串但不匹配计数的行)解释中的缩进级别表示花括号嵌套的级别。
所有其他行无需处理即可通过并打印。