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
- 交换模式空间并保持空间(激活匹配字符串但不匹配计数的行)解释中的缩进级别表示花括号嵌套的级别。
所有其他行无需处理即可通过并打印。