数据文件 - data.txt:
ABC "I am ABC" 35 DESC
DEF "I am not ABC" 42 DESC
cat data.txt | awk '{print $2}'
将导致“I”而不是引用的字符串
如何制作awk以便忽略引号中的空格并认为它是一个单一的标记?
答案 0 :(得分:8)
另一种选择是使用FPAT
变量,它定义描述每个字段内容的正则表达式。
将此AWK脚本另存为parse.awk
:
#!/bin/awk -f
BEGIN {
FPAT = "([^ ]+)|(\"[^\"]+\")"
}
{
print $2
}
使其chmod +x ./parse.awk
可执行,并将您的数据文件解析为./parse.awk data.txt
:
"I am ABC"
"I am not ABC"
答案 1 :(得分:7)
是的,这可以在awk中很好地完成。没有任何严重的黑客攻击很容易获得所有领域。
(此示例适用于The One True Awk和gawk。)
{
split($0, a, "\"")
$2 = a[2]
$3 = $(NF - 1)
$4 = $NF
print "and the fields are ", $1, "+", $2, "+", $3, "+", $4
}
答案 2 :(得分:5)
试试这个:
$ cat data.txt | awk -F\" '{print $2}'
I am ABC
I am not ABC
答案 3 :(得分:3)
此问题的最佳答案仅适用于带有单引号字段的行。当我发现这个问题时,我需要一些可以用于任意数量的引用字段的东西。
最终我遇到了an answer by Wintermute in another thread,他为这个问题提供了一个很好的通用解决方案。我刚修改它以删除引号。请注意,在运行以下程序时,您需要使用-F\"
调用awk。
BEGIN { OFS = "" } {
for (i = 1; i <= NF; i += 2) {
gsub(/[ \t]+/, ",", $i)
}
print
}
这可以通过观察当你用“-character”分隔时数组中的每个其他元素都在引号内部,因此它用逗号代替除了引号之外的空格。
然后,您可以轻松地链接另一个awk实例来执行您需要的任何处理(只需再次使用字段分隔符开关,-F,
)。
请注意,如果引用第一个字段,这可能会中断 - 我还没有测试过。但是,如果确实如此,则应该很容易通过添加if语句来从2开始而不是1,如果该行的第一个字符是“。
答案 4 :(得分:2)
我把一个将$ 0重新拆分成一个名为B的数组的函数拼凑在一起。双引号之间的空格不作为字段分隔符。可与任意数量的字段一起使用,包括引用和未引用的字段。这是:
#!/usr/bin/gawk -f
# Resplit $0 into array B. Spaces between double quotes are not separators.
# Single quotes not handled. No escaping of double quotes.
function resplit( a, l, i, j, b, k, BNF) # all are local variables
{
l=split($0, a, "\"")
BNF=0
delete B
for (i=1;i<=l;++i)
{
if (i % 2)
{
k=split(a[i], b)
for (j=1;j<=k;++j)
B[++BNF] = b[j]
}
else
{
B[++BNF] = "\""a[i]"\""
}
}
}
{
resplit()
for (i=1;i<=length(B);++i)
print i ": " B[i]
}
希望它有所帮助。
答案 5 :(得分:0)
好的,如果你真的想要所有三个领域,你可以得到它们,但它需要很多管道:
$ cat data.txt | awk -F\" '{print $1 "," $2 "," $3}' | awk -F' ,' '{print $1 "," $2}' | awk -F', ' '{print $1 "," $2}' | awk -F, '{print $1 "," $2 "," $3}'
ABC,I am ABC,35
DEF,I am not ABC,42
通过最后一根烟斗你可以得到所有三个字段来做任何你喜欢的事情。
答案 6 :(得分:0)
这是我最终工作的东西,对我的项目更通用。 请注意,它不使用awk。
http = 0.0.0.0:8080
哪个输出:
someText="ABC \"I am ABC\" 35 DESC '1 23' testing 456"
putItemsInLines() {
local items=""
local firstItem="true"
while test $# -gt 0; do
if [ "$firstItem" == "true" ]; then
items="$1"
firstItem="false"
else
items="$items
$1"
fi
shift
done
echo "$items"
}
count=0
while read -r valueLine; do
echo "$count: $valueLine"
count=$(( $count + 1 ))
done <<< "$(eval putItemsInLines $someText)"