AWK,同一文件中使用不同分隔符打印 2 次

AWK, 2 prints with different separators from the same file

假设我有这条线

"58062","2022-03-23 10:07:21.718670","Standard query 0x04c0 AAAA contoso.local"

我只想打印“contoso.local”,这是双引号内最后一个块的第 5 列。

我这样做得到了我想要的:

cat file.log | awk -F "," '{print }' | awk '{print }'

有没有更优雅的方法来实现这个?我在第一个 awk 中尝试了一个 awk,但这不起作用,我相信我使用的是 Ubuntu 18.

中的 GNU Awk

编辑:

这确实是一个日志文件(很多过滤的 dns 查询),其中所有行都具有相同的结构,更具体地说:我并不严格需要该行的最后一个词,例如我可能需要提取域之前的字母数字代码,它始终是最后一个块的第 3 列。

"58062","2022-03-23 10:07:21","Standard query 0x04c0 A contoso.local"
"58063","2022-03-23 10:08:22","Standard query 0xcif0 A something.local"
"58064","2022-03-23 10:09:23","Standard query 0xEec0 AAAA domain.local"

以上文件有效:

cat file.log | awk -F "," '{print }' | awk '{print }'

另一种选择是简单地使用 sed 和通常的替换 ('s/find/replace/' file) 捕获行中最后一个空格分隔的文本到第一个 '"' 并重新插入该文本使用第一个命名的反向引用。

sed -E 's/^.*[[:space:]]([^"]+)"$//'

上面的 -E 选项指定了 扩展正则表达式 语法。如果您的 sed 不支持 -E(或 -r),您只需用 *(零次或多次出现)再次声明匹配并转义capture-group 中的括号。使用基本正则表达式将是:

sed -E 's/^.*[[:space:]]\([^"][^"]*\)"$//'

例子Use/Output

使用 file 中的示例行,您将得到:

$ sed -E 's/^.*[[:space:]]([^"]+)"$//' file
contoso.local

这取决于你的数据。如果问题是:'Print the last "word" without ending quote',那么可能是:

sed -E 's/.* (.*)"//'
awk -F'.* |"' '{[=10=]=}1'
# grep -oP '([^\s]+)(?="$)' file.log 
contoso.local
something.local
domain.local

1.grep 支持 lookaround,你需要在你的 grep 中添加 -P 选项(如果你的 grep 支持的话)。因为 PCRE 支持它们。

2.\s匹配任意空格,^表示否定,+表示匹配一次或多次,"$表示以引号结尾

以上评论来自@JNevill的回答

awk -F"," '{split(,a,"[  \"]"); print a[5]}' test.txt

对我的评论进行一些澄清:

gawk -F"," '{ FS=" "; [=10=]=; print  }' file.log

这在 file.log 只有一行时有效,而在包含多行时无效。这可以通过以下方式解决:

gawk -F"," '{ FS=" "; [=11=]=; print ; FS="," }' file.log

步骤:

  1. -F"," 字段分隔符设置为逗号
  2. FS=" " 字段分隔符设置为 space。这是在阅读第一行后完成的。
  3. [=16=]= Re-assinging [=17=] 具有一个值(在本例中为 </code>)将使 gawk 再次拆分该值,由 <code>FS.
  4. print 打印第 5 个字段。
  5. FS="," 将字段分隔符重新设置为“,”以处理下一行。

因为多次给 FS 赋值,所以最好使用 split()

这将导致:

gawk -F"," '{ split(,a," "); print a[5] }' file.log

(JNevil 在评论中也给出了)

如果您非常确定您需要的是 </code> 的最后一个 space/tab 之后,那么 </p> <pre><code> # using FS to deal with trailing double-quote mawk 'sub("^.+ ",_,$(($!_=$_=)<_))' FS=',|["]$' or # using gsub() to deal with trailing double-quote mawk 'gsub("^.+ |["]$",_,$(NF=($_=)~_))' FS=',' or #using RS to deal with trailing double-quote mawk 'sub("^.+ ",_,$(NF=($_=)~_))' FS=',' RS='"?\n' "58062","2022-03-23 10:07:21","Standard query 0x04c0 A contoso.local" "58063","2022-03-23 10:08:22","Standard query 0xcif0 A something.local" "58064","2022-03-23 10:09:23","Standard query 0xEec0 AAAA domain.local" contoso.local something.local domain.local

或者也许

 echo "${aaa}" \
 \
 | mawk 'BEGIN { FS=_="," 
   
   } $!+_=$+(FS=_)=substr("",$(($!+_=)<"")=$+(FS=" |[]$")) $--NF'  

contoso.local
something.local
domain.local