sed -r ':a; s/^((([^"]*"){2})*[^"]*"[^" ]*) /\1_/;ta'
4444 username "some_information" "someotherinformation" "even_more_information"
或者
sed ':a; s/^\(\(\([^"]*"\)\{2\}\)*[^"]*"[^" ]*\) /\1_/;ta'
4444 username "some_information" "someotherinformation" "even_more_information"
:a
- 为循环标记“a”
s///
- 执行替换
^(
- 将整个搜索字符串锚定在行首
(([^"]*"){2})*
- 捕获(在第 1 组中)两组零个或多个非引号,后跟一个引号(零次或多次)
[^"]*"
- 后跟零个或多个非引号,后跟一个引号
[^" ]*
- 后跟零个或多个不是空格或引号的字符
)
- 结束锚定序列并寻找需要替换的空间
\1
- 将捕获的组和下划线替换为匹配的序列
ta
- 分支(转移执行)标记:a
是否成功替换(如果没有成功,则继续执行下一条指令 - 在这种情况下,该指令结束这一行的处理并读取下一条,开始新一轮的处理)
这会在最后一个带引号的字符串中找到第一个空格并替换它。然后下一个,如果有的话,直到引用的字符串完成。等等任何额外的空间。
然后下一个包含空格的先前引用的字符串......等等。
:a
这就是模式空间在...ta
循环的每一步中的样子:
4444 username "some information" "someotherinformation" "even_more information"
4444 username "some information" "someotherinformation" "even_more_information"
4444 username "some_information" "someotherinformation" "even_more_information"
然后它会多走几次以查找行首的任何匹配项。