【问题标题】:Can field separator in awk encompass multiple characters?awk 中的字段分隔符可以包含多个字符吗?
【发布时间】:2012-01-05 16:05:19
【问题描述】:

我可以使用由多个字符组成的字段分隔符吗?就像我想分隔它们之间包含引号和逗号的单词。

“学校”、“大学”、“城市”

所以在这里我想将我的 FS 设置为“,”。但是当我这样定义我的 FS 时,我得到了有趣的结果。这是我的代码的 sn-p。

awk -F\",\" '
{
for(i=1;i<=NF;i++)
  {
    if($i~"[a-z0-9],[a-z0-9]") 
    print $i
  }
}' OFS=\",\"  $* 

【问题讨论】:

  • 你看到的这些“有趣的结果”是什么?

标签: awk gawk


【解决方案1】:

是的,FS 可以是多字符。用你的例子看下面的测试:

kent$  echo '"School","College","City"'|awk -F'","|^"|"$' '{for(i=1;i<=NF;i++){if($i)print $i}}'
School
College
City

【讨论】:

    【解决方案2】:

    这里讨论的是字段分隔符不仅限于多个字符,而且实际上可以是一个成熟的正则表达式。

    也就是说: 这会从 XML 片段中去除标题和周围的标记。 请注意,标签格式正确,但不同。

    bash-3.2$ more xml_example 
    <?xml version="1.0" encoding="UTF-8"?>
    <urlset
    xmlns="http://www.google.com/schemas/sitemap/0.84"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.google.com/schemas/sitemap/0.84
                      http://www.google.com/schemas/sitemap/0.84/sitemap.xsd">
    <url>
    <loc>http://www.foo.com/about.html</loc>
    <lastmod>2006-05-15T13:43:37Z</lastmod>
    <priority>0.5000</priority>
    </url>
    <url>
    <loc>http://www.foo.com/articles/articles.html</loc>
    <lastmod>2006-06-20T23:03:36Z</lastmod>
    <priority>0.5000</priority>
    </url>
    

    现在我们应用 awk 脚本打印出中间字段,使用正则表达式作为字段分隔符:

    bash-3.2$ awk -F"<(/?)[a-z]+>" '{print $2}' <xml_example
    
    
    
    
    http://www.foo.com/about.html
    2006-05-15T13:43:37Z
    0.5000
    
    
    http://www.foo.com/articles/articles.html
    2006-06-20T23:03:36Z
    0.5000
    
    bash-3.2$
    

    空行是从该行唯一的标签开始的,因此没有 $2 可打印。 这实际上非常强大,因为这意味着您不仅可以使用具有多个字符的固定模式,还可以在字段分隔符中使用正则表达式的全部功能。

    【讨论】:

    • 可以打印标签吗?你能访问FS匹配的字符串并打印吗?
    【解决方案3】:

    试试

    awk 'BEGIN{FS="[|,:]"}{print $1}' youFile
    

    【讨论】:

      【解决方案4】:

      使用 GNU awk 4,您甚至可以轻松解析带有嵌入分隔符和引号的 *CSV*s:

      % cat infile 
      "School",College: "My College","City, I"
      
      % awk '{    
        for (i = 0; ++i <= NF;)
          print i, substr($i, 1, 1) == "\042" ?
            substr($i, 2, length($i) - 2) : $i
        }' FPAT='([^,]+)|(\"[^\"]+\")' infile  
      1 School
      2 College: "My College"
      3 City, I
      

      【讨论】:

        【解决方案5】:

        是的,-F 参数可以使用多个字符,因为该值可以是正则表达式。例如,您可以执行以下操作:

        echo "hello:::my:::friend" | gawk -F':::' '{print $3}'
        

        这将返回friend

        支持正则表达式作为-F 的参数对于nawkgawk (GNU awk) 是正确的,原来的awk 不支持它。在 Solaris 上,这种区别很重要,在 Linux 上并不重要,因为awk 实际上是到gawk 的链接。因此,我认为将 awk 调用为 gawk 是最佳实践,因为这样它将跨平台工作。

        【讨论】:

          【解决方案6】:

          要使用 awk 以多个字符分隔并完全以 "," 分隔,您可以在字符前添加 \\

          echo '"School","College","City"'|awk -F'\\\\"\\\\,\\\\"' '{for(i=1;i<=NF;i++){if($i)print $i}}'
          

          https://es.stackoverflow.com/questions/422811/unix-awk-separaci%c3%b3n-de-campos-por-grupo-de-caracteres/423081#423081

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-10-14
            • 2013-03-17
            • 1970-01-01
            • 2017-08-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多