【问题标题】:How do I get awk to NOT use space as a delimeter?如何让 awk 不使用空格作为分隔符?
【发布时间】:2013-11-25 03:13:22
【问题描述】:

我有一个我正在尝试处理的 CSV,但我的一些字段包含逗号、换行符和空格,现在我考虑一下,其中可能还有一些撇号。

对于逗号和换行符,我已在输出阶段将它们转换为其他字符串,并在最后将它们转换回来(是的,这很混乱,但我只需要运行一次)我意识到我可能必须这样做这也有空格,但我已将问题分解为基本部分,看看我是否可以解决它

这是一个 input.csv

"john","beatles.com","arse","fool@wonka.com","1","1","on holiday"
"paul","beatles.com","bung","","0","1","also on holiday"

(我试过加引号和不加引号)

这是脚本

INPUT="input.csv"

for i in `cat ${INPUT}`

do
#USERNAME=`echo $i | awk -v  FS=',' '{print $1}'`
USERNAME=`echo $i | awk 'BEGIN{FS="[|,:]"} ; {print $1}'`
echo "username: $USERNAME"

done

所以应该只输入 john 和 paul 但我得到了

username: "john"
username: holiday"
username: "paul"
username: on
username: holiday"

因为它会看到空格并将它们解释为新行。

我可以让它停止吗?

【问题讨论】:

  • 也许只写一个四行Python脚本?内置的csv 模块可以解析这个没问题。
  • 你的for i in $(cat ...)有问题:i将依次取值"john","beatles.com","arse","fool@wonka.com","1","1","onholiday" "paul","beatles.com","bung","","0","1","alsoonholiday"。这不是awk 的问题。
  • 永远不要使用for i in $(cat ...)。这是谁给你看的?找到他,让他知道他不仅做错了事,而且还在传播不良做法,浪费你的时间。你真的应该生他的气。
  • 现在,只是为了确保您做对了:不要使用awksedbash 等解析 csv 文件。 使用正确的 csv解析器。其中有很多在 Python、Perl 等方面非常出色(这只是一个建议,这样您就不会浪费时间在从一开始就被破坏的方法上)。
  • 获取 Arnold Robbins 的《Effective Awk Programming, Third Edition》一书(快!),然后按预期只使用 shell 调用工具。

标签: bash csv awk space


【解决方案1】:

导致分词的不是awk,而是shell(IFS的默认值)。

你可以这样解决这个问题:

while read -r i; do
  USERNAME=$(echo "$i" | awk 'BEGIN{FS="[|,:]"} ; {print $1}');
  echo "username: $USERNAME";
done < $INPUT

为了验证 shell 是如何读取输入的,添加

echo "This is a line: ${i}"

在循环中。

【讨论】:

    【解决方案2】:

    您可以在 awk 中使用任何正则表达式字段分隔符,例如使用可选的逗号后跟双引号:

    awk -F ',?"' '{print $2, $4, $6, $8, $10, $12, "<" $14 ">"}' f1
    john beatles.com arse fool@wonka.com 1 1 <on holiday>
    paul beatles.com bung  0 1 <also on holiday>
    

    附上最后一个字段 $14 n &lt; and &gt; 以展示它是如何进入单个 awk 变量的。

    【讨论】:

      【解决方案3】:

      有几点需要注意,您不需要使用catfor 循环。除非我错过了更大的图景......

      对文件调用 awk 会发生什么?

      awk -F"," '{print $1}' input.csv
      

      我得到以下信息:

      $ awk -F"," '{print $1}' input.csv
      "john"
      "paul"
      $
      

      【讨论】:

        【解决方案4】:

        无需 awk 的解决方案:

        cut -d, -f1 input.csv | while read -r USERNAME ; do echo "username: ${USERNAME}" ; done
        

        以上假设您要保留引号。如果没有……

        cut -d, -f1 input.csv | sed 's,^",,;s,"$,,' | while read -r USERNAME ; do echo "username: ${USERNAME}" ; done
        

        以上都假设您的字段内容中没有逗号。如果不是这样,请在您最喜欢的脚本语言中使用“适当的”CSV 解析器。示例...

        ruby -rcsv -ne 'puts CSV.parse_line($_)[0]' input.csv | while read -r USERNAME ; do echo "username: ${USERNAME}" ; done
        

        【讨论】:

          猜你喜欢
          • 2015-01-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-06
          • 1970-01-01
          • 1970-01-01
          • 2016-01-05
          • 1970-01-01
          相关资源
          最近更新 更多