2014-10-08 156 views
0

我正在寻找一种简单的方法,在允许嵌入空间的情况下使用awk打印特定字段。用AWK忽略嵌入空格

样品:Field1 Field2 "Field Three" Field4

我希望能够以相当于做awk '{print $3}'但得到“第三场”作为一个单一的领域而不是两个。

更新:更具体地说,我需要得到后来的领域不是3美元,但#3的空间是什么搞砸了。 $ 3中引号之间的空格数量是可变的。即使并非所有字段都被引用,我只是希望能够将引号之间的内容视为单个字段。所以,如果在引号之间,忽略空格作为字段分隔符。

回答

1

你可以做到这一点,如果双引号始终存在:

awk -F\" '{print $2}' 

具体来说,我告诉awk的字段都用双引号分开,此时您需要的部分是现成的场2.

如果您需要获得在随后的场,你可以分割的空间行的剩余部分,并得到一个新的数组,说田F[],像这样:

awk -F\" '{split($3,F," ");print $2,F[1],F[2]}' file 

Field Three Field4 Field5 

假设你的文件是这样的:

Field1 Field2 "Field Three" Field4 Field5 Field6 
+0

是的,这给我确切的场3,但不能得到后期的领域。 – 2014-10-09 20:45:12

+0

我没有意识到你想要后期的领域。我已经添加了一种应对方式,所以请再看一下。 – 2014-10-09 21:13:33

+0

太棒了。这给我一个我需要的技巧,并能够将其调整为真实的数据。 (27个字段,引用空格的倍数。)[对不起,是一个偏执的安全人员。]谢谢你的帮助! – 2014-10-10 19:07:12

0

马克·瑟特查的回答是好,但如果你事先不知道你有多少个嵌入式引号将无法正常工作(它不各执空间了)。

我砍死了一起(这显然可以提高):

gawk -v FIELD=2 '{ a=$ FIELD; if (substr(a, 0, 1) == "\"") { gsub(/^\"/, "", a); s=a; for (i = FIELD + 1; i <= NF; i++) { a=$ i; nbSub=gsub(/\"$/, "", a); s = s " " a; if (nbSub > 0) { break } } print(s) } }' <<<'allo "hello world" bar' 

我会建议使用的东西比呆呆地看着这个别人(可能考虑与解析你的shell变量IFS领域?)。

附录:如上所述,这不是真正适合这项工作的工具。例如,您可以使用-v FIELD =指定第一个字段,但是它会基于AWK的分隔符计算字段(嵌入的空间仍会计数)。

+0

谢谢大家的意见,但这些都不能帮助我。 也许我的总体目标还不够清楚。 (试图保持简单的问题。) 更具体地说,我需要得到后来的领域不是3美元,但在3美元的空间是什么东西搞砸了。 $ 3中引号之间的空格数量是可变的。即使并非所有字段都被引用,我只是希望能够将引号之间的内容视为单个字段。所以,如果在引号之间,忽略空格作为字段分隔符。 有没有其他想法?我希望这显然更困难。 – 2014-10-09 20:38:28

1

基于this,在gawk也许你可以使用类似

awk 'BEGIN{FPAT = "([^ ]+)|(\"[^\"]+\")"}{print $3}' input.txt 

输出:

"Field Three" 

它可能需要更多的工作来获取适合您的需求完全。

我觉得需要gawk 4+,https://lists.gnu.org/archive/html/info-gnu/2011-06/msg00013.html

+0

这似乎与基本{print $ 3}的效果完全相同。我得到#3的前1/2。 – 2014-10-09 20:44:36

+0

@ Chris-9090,它是'gawk'特定的,需要版本4或更高版本。你在使用GNU awk('gawk')还是其他一些实现?试试'awk --version'来查看你正在使用哪个实现。为了这个工作,输出应该看起来像'GNU Awk 4.1.0,API:1.0' – Ashkan 2014-10-10 06:47:34

1

解析CSV可以是一个棘手的业务。我喜欢使用适当的CSV解析模块的语言。例如红宝石,解析给定的线,使用空格作为列分隔符,以及默认双引号引号字符:

ruby -rcsv -ne 'row = CSV.parse_line($_, {:col_sep=>" "}); puts row[2]' <<END 
Field1 Field2 "Field Three" Field4 
END 
Field Three 
+0

对不起,我没有在这个系统上访问Ruby。 – 2014-10-09 20:44:16

0

马克·瑟特查的解决方案为我工作最好的:

awk -F\" '{split($3,F," ");print $2,F[1],F[2]}' file