相关文章推荐
腼腆的凳子  ·  mysql ...·  1 周前    · 
千杯不醉的甘蔗  ·  SQL Server ->> SET ...·  1 月前    · 
温文尔雅的菠萝  ·  W: 无法下载 ...·  1 年前    · 

Awk将双引号字符串视为一个标记,并忽略其间的空格

内容来源于 Stack Overflow,遵循 CC BY-SA 4.0 许可协议进行翻译与使用。IT领域专用引擎提供翻译支持

腾讯云小微IT领域专用引擎提供翻译支持

原文
Stack Overflow用户 修改于2011-07-08
  • 该问题已被编辑
  • 提问者: Stack Overflow用户
  • 提问时间: 2011-07-08 11:12

数据文件- data.txt:

ABC "I am ABC" 35 DESC
DEF "I am not ABC" 42 DESC

cat data.txt | awk '{print $2}'

将产生"I“而不是被引号的字符串。

如何使awk忽略引号中的空格,并认为它是一个单独的令牌?

浏览 142 关注 0 得票数 27
  • 得票数为Stack Overflow原文数据
原文
修改于2011-07-08
  • 该回答已被编辑
  • 回答者: Stack Overflow用户
  • 回答时间: 2011-07-08 11:22
得票数 5

试试这个:

$ cat data.txt | awk -F\" '{print $2}'
I am ABC
I am not ABC
修改于2011-07-08
  • 该回答已被编辑
  • 回答者: Stack Overflow用户
  • 回答时间: 2011-07-08 11:57
得票数 9

是的,这可以在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
}
回答于2011-07-08
得票数 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

在最后一条管道中,您已经获得了所有三个字段,可以随心所欲地处理。

回答于2013-05-28
得票数 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]
      B[++BNF] = "\""a[i]"\""
  resplit()
  for (i=1;i<=length(B);++i)
    print i ": " B[i]
}

希望能有所帮助。

修改于2017-05-23
  • 该回答已被编辑
  • 回答者: Stack Overflow用户
  • 回答时间: 2015-10-23 16:54
得票数 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开始,应该很容易修复。

评论 0
0
回答于2016-01-16
得票数 0

这是我最终得到的一些东西,它对我的项目更通用。注意,它不使用awk。

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"
            items="$items
        shift
    echo "$items"
count=0
while read -r valueLine; do
    echo "$count: $valueLine"
    count=$(( $count + 1 ))
done <<< "$(eval putItemsInLines $someText)"

以下哪项输出:

0: ABC
1: I am ABC
2: 35
3: DESC
4: 1 23
5: testing
6: 456
回答于2017-04-05
得票数 20

另一种选择是使用 FPAT 变量,该变量定义一个正则表达式来描述每个字段的内容。

将此AWK脚本另存为 parse.awk

#!/bin/awk -f
BEGIN {