我一直在使用sep来尝试这个,基本上我有一个文本文件,其中包含相同数量的相同行,例如。
4444 username "some information" "someotherinformation" "even more information"
我需要用下划线替换引号内的空格,使它看起来像这样
4444 username "some_information" "someotherinformation" "even_more_information"
目前我已经能够分开引用的信息
sed 's/"\([^"]*\)"/_/g' myfile.txt
关于如何进行的建议?
答案 0 :(得分:6)
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"
然后它会再次进行几次寻找行开头的任何匹配。
答案 1 :(得分:3)
的 EDITED 强> 的
以前的版本会添加不需要的空格。这个版本完全符合OP的要求。
这可能是获得你想要的最简单方法。
awk -F'"' '
BEGIN {
OFS="\""
}
{
for (i = 2; i < NF; i += 2) {
gsub(/[ \t]+/, "_", $i)
}
print $0
}
' file > outputFile
答案 2 :(得分:0)
我实际上是在C中执行此操作,这使得比大多数高级语言更容易执行逐个字符的状态机。
#include <stdio.h>
int main(void)
{
int inside_quotes = 0;
int backslash = 0;
int c;
while ((c = getchar()) != EOF) {
switch (c) {
case ' ':
if (inside_quotes)
c = '_';
break;
case '"':
if (!backslash)
inside_quotes = !inside_quotes;
break;
case '\\':
if (!backslash)
backslash = 2;
break;
default:
break;
}
if (backslash > 0) backslash--;
putchar(c);
}
return 0;
}
未测试甚至未编译。特别是反斜杠处理很可能是错误的。
答案 3 :(得分:0)
这可能对您有用:
echo '4444 username "some information" "someotherinformation" "even more information"' |
sed 's/"[^"]*"/\n&/g;:a;s/\(\n"[^"]*\) /\1_/g;ta;s/\n//g'
4444 username "some_information" "someotherinformation" "even_more_information"
\n
)。 sed 's/"[^"]*"/\n&/g;
_
。 :a;s/\(\n"[^"]*\) /\1_/g;ta
s/\n//g