Bash 用单制表符替换空格,除非使用双引号
假设一个多行文件,其中的字符串由一个或多个空格分隔。进一步假设字符串组可以用双引号括起来Bash 用单制表符替换空格,除非使用双引号,bash,awk,Bash,Awk,假设一个多行文件,其中的字符串由一个或多个空格分隔。进一步假设字符串组可以用双引号括起来 > cat file foo bar "foobar baz qux" foo "bar foobar baz" qux "foo bar foobar" baz qux # multiple whitespaces in this line 如果我希望使用如下所列的awk将双引号外的所有空格替换为单制表符,我将收到以下消息: awk '{OFS="\t"; FPAT="([^, ]+)
> cat file
foo bar "foobar baz qux"
foo "bar foobar baz" qux
"foo bar foobar" baz qux # multiple whitespaces in this line
如果我希望使用如下所列的awk将双引号外的所有空格替换为单制表符,我将收到以下消息:
awk '{OFS="\t"; FPAT="([^, ]+)|(\"[^\"]+\")"; $1=$1; print}' file
# foo bar "foobar baz qux" # In this line, strings inside the quote are separated by tabs
# foo "bar foobar baz" qux
# "foo bar foobar" baz qux
问题似乎只限于以双引号结尾的行
编辑1:
为了更好地了解当前的问题:
awk '{OFS="\t"; FPAT="([^, ]+)|(\"[^\"]+\")"; $1=$1; print}' file | cat -A
# foo^Ibar^I"foobar^Ibaz^Iqux"$
# foo^I"bar foobar baz"^Iqux$
# "foo bar foobar"^Ibaz^Iqux$
编辑2:
除非输入中存在一定数量或非字母字符组合,否则答案部分中建议的两个命令都可以正常工作。以下是一个例子:
> cat file
foo_bar_baz foo foo_bar . Name=foo;product="bar baz qux"
foo_bar_baz foo foo_bar . Name=foo;product="bar baz qux"
foo_bar_baz foo foo_bar . Name=foo;product="bar baz qux"
> awk -v FPAT='"[^"]*"|[^[:blank:]]+' -v OFS='\t' '{$1=$1} 1' file | cat -A
foo_bar_baz^Ifoo^Ifoo_bar^I.^IName=foo;product="bar^Ibaz^Iqux"$
foo_bar_baz^Ifoo^Ifoo_bar^I.^IName=foo;product="bar^Ibaz^Iqux"$
foo_bar_baz^Ifoo^Ifoo_bar^I.^IName=foo;product="bar^Ibaz^Iqux"$
> awk '{$1=$1}1' OFS='\t' FPAT='"[^"]+"|[^ ]+' file | cat -A
foo_bar_baz^Ifoo^Ifoo_bar^I.^IName=foo;product="bar^Ibaz^Iqux"$
foo_bar_baz^Ifoo^Ifoo_bar^I.^IName=foo;product="bar^Ibaz^Iqux"$
foo_bar_baz^Ifoo^Ifoo_bar^I.^IName=foo;product="bar^Ibaz^Iqux"$
编辑3:
编辑2提出的这个问题将在此处进一步讨论:使用
gnu awk
您可以轻松做到这一点:
awk -v FPAT='"[^"]*"|[^[:blank:]]+' -v OFS='\t' '{$1=$1} 1' file
foo bar "foobar baz qux"
foo "bar foobar baz" qux
"foo bar foobar" baz qux
我将使用以下命令:
awk '{$1=$1}1' OFS='\t' FPAT='"[^"]+"|[^ ]+'
我通过FPAT
变量定义了两种可能的字段:
- 用双引号括起来的字符串
“[^”]+”
- 非空白字符序列
[^]+
awk '{$1=$1}1' OFS='\t' FPAT='"[^"]+"|[^ ]+' a.txt | cat -A
输出:
foo^Ibar^I“foobar baz qux”$
foo^I“bar foobar baz”^iqx$
“foobar foobar”^Ibaz^iqx$
您的命令工作得非常出色。但是,为什么上面的示例会在第一行中替换双引号之间的空格?这是因为您设置FPAT
太晚了。应该像我所示从命令行或BEGIN
块中设置,以便从第1行开始生效,例如awk'BEGIN{OFS=“\t”;FPAT=“([^]+)|(\"[^\"]+\")"} {$1=$1}1'file
也应该适用于您。哦,您已经在评论中提到了它。我将删除我的答案,然后…@anubhava在使用您的awk命令几天后,它似乎只在非常特定的情况下有效。例如,以下文件未按预期处理:>cat文件
foo\u-bar\u-baz-foo\u-bar.Name=foo;product=“bar-baz-qux”\nfo\u-bar\u-baz-foo-foo-bar.Name=foo;product=“bar-baz-qux”\nfo\u-bar\u-baz-foo\u-bar.Name=foo;product=“bar-baz-qux”
与用户anubhava的代码一样,以下文件未按预期处理,可能是由于存在非字母字符:>cat文件
foo\u bar\u baz foo\u bar.Name=foo;product=“bar baz qux”\nfo\u bar\u baz foo\u bar.Name=foo;product=“bar baz qux”\nfo\u bar\u baz foo\u bar.Name=foo;product=“bar baz-qux”
您将如何调整代码以处理非字母字符的存在?@MichaelGruenstaeudl您能将该示例添加到您的问题中吗?很难在评论中理解。请不要编辑现有示例,添加新示例(甚至打开新问题)新的例子已经附加到问题中。好问题。我不知道atm。将需要对此进行调查