【问题标题】:Replace special characters in variable in awk shell command在 awk shell 命令中替换变量中的特殊字符
【发布时间】:2014-07-29 14:05:51
【问题描述】:

我目前正在执行以下命令:

awk 'BEGIN { FS="," ; getline ; H=$0 } N != $3 { N=$3 ; print H > "/Directory/FILE_"$3"_DOWNLOAD.csv" } { print > "/Directory/FILE_"$3"_DOWNLOAD.csv" }' /Directory/FILE_ALL_DOWNLOAD.csv

这会从 CSV 文件中的第三个位置获取值,并为每个不同的 $3 值创建一个 CSV。按需要工作。

输入文件如下:

Name, Amount, ID
"ABC", "100.00", "0000001"
"DEF", "50.00", "0000001"
"GHI", "25.00", "0000002"

不幸的是,我无法控制源 (CSV) 表中的值,即 $3 值,但我想从中删除特殊(非字母数字)字符。我尝试了以下方法来完成此操作,但失败了...

awk 'BEGIN { FS="," ; getline ; H=$0 } N != $3 { N=$3 ; name=${$3//[^a-zA-Z_0-9]/}; print H > "/Directory/FILE_"$name"_DOWNLOAD.csv" } { print > "/Directory/FILE_"$name"_DOWNLOAD.csv" }' /Directory/FILE_ALL_DOWNLOAD.csv

建议?我希望在一个命令中执行此操作,但如果有人有一个可行的 bash 脚本答案。

【问题讨论】:

  • 源文件中的示例记录:“123.”、“公司名称”“456.”生成一个文件 /Directory/FILE_" 456."_DOWNLOAD.csv - 我正在寻找 /Directory/FILE_456_DOWNLOAD.csv -- 谢谢。
  • 编辑您的问题并从文件中添加几行会很有用。
  • 我很好奇 - 你从哪里得到 name=${$3//[^a-zA-Z_0-9]/} 语法的想法?
  • @Ed 在我看来像是 awk 字段上的 bash 替换的混合体。
  • 哦,我明白了 - 如果这是 bash 并且 $3 是 bash 变量.... 明白了,谢谢。

标签: bash shell unix awk


【解决方案1】:

这绝对不是你应该使用getline 的工作,请参阅http://awk.info/?tip/getline

看起来您只想在每个以 $3 命名的文件中重现输入文件的第一行。那是:

awk -F, '
NR==1 { hdr=$0; next }
$3 != prev { prev=name=$3; gsub(/[^[:alnum:]_]/,"",name); $0 = hdr "\n" $0 }
{ print > ("/Directory/FILE_" name "_DOWNLOAD.csv") }
' /Directory/FILE_ALL_DOWNLOAD.csv

请注意,您必须始终在输出重定向 (>) 的右侧为表达式加上括号,否则会产生歧义,并且如果不这样做,不同的 awk 的行为会有所不同。

如果您愿意,可以将它们全部放回一行。

【讨论】:

  • +1 啊,是的,[:alnum:] 是我一直在寻找的东西 - 出于某种原因,我尝试在每一侧使用两个 [[ ]],所以它不起作用。
  • 难道你不能只使用关联数组而不是 prev 吗?实际上从 OPs 描述中creates a CSV for each distinct $3 value 是否有必要进行比较?
  • 这里与prev 的比较是在每个文件中仅添加一次hdr 前缀(每次运行$3 值一次,但这是每个OP 规范)。
【解决方案2】:

如果您总是希望数字出现在 CSV 的最后一个字段中,并且您知道每个字段都用引号括起来,则可以使用此 awk 从您在评论中提供的输入中提取值 456

echo " 123.", "Company Name" " 456." | awk -F'[^a-zA-Z0-9]+' 'NF { print $(NF-1) }'

这将字段分隔符定义为任意数量的非字母数字字符并检索倒数第二个字段。

如果这足以可靠地检索值,您可以像这样构造文件名:

file = "/Directory/FILE_" $(NF-1) "_DOWNLOAD.csv"

并像你已经在做的那样输出到它。

【讨论】:

    【解决方案3】:

    bash 变量扩展不会出现在单引号中。

    它们也不能在 awk 变量上执行。

    话虽如此,你不需要它来工作。

    awk 具有可以执行相同任务的字符串操作函数。在这种情况下,您可能需要gsub 函数。

    【讨论】:

    • 在我看来像是一条评论!
    • @TomFenech 我最初将其写为评论,然后意识到它实际上回答了正在询问的“如何规范化字段数据”的问题。
    【解决方案4】:

    这不符合您的要求吗?

    awk -F, 'a=NR==1{x=$0;next}
    !a{gsub(/[^[:alnum:]]/,"",$3);print x"\n"$0 >> "/Directory/FILE_"$3"_DOWNLOAD.csv"}' file
    

    【讨论】:

    • 另一个问题回答了一个问题! ;)
    猜你喜欢
    • 2016-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 1970-01-01
    • 2014-10-19
    • 2014-07-29
    • 1970-01-01
    相关资源
    最近更新 更多