【问题标题】:AWK - passing generated string as code for awk from command lineAWK - 从命令行传递生成的字符串作为 awk 的代码
【发布时间】:2014-07-29 20:36:58
【问题描述】:

我正在尝试使用 awk 动态打印文件的选定字段。

基本上,问题是为什么这个有效:

awk -F';' '{print $3 ";" $4 ";" }' file

但事实并非如此:

awk -F';' '{print '`echo '$3 ";" $4 ";"'`' }' file

我的最终目标是将上述内容封装在一个命令中,以便我能够做到

my_cmd ';' 3 6 7 8 file(s)

它应该显示由;file(s) 分隔的字段#3,6,7,8

编辑我的帖子: 自己发现我的问题是回声当然是插入了一个新行字符,这导致 awk 出现问题:o) \c 成功了,还有一些 \" 转义必须做(见下文)。

awk -F';' '{print '"`echo '$3 \";\" $4 \";\"\c'`"' }' file(s)

现在我只剩下用命令来更改它了,该命令将生成一个类似的字符串 $2 ";' $5 ";' $6 ";' $9 ";"(数字和字段应该是输入)等应该介于'{print '' }'之间

感谢 cbuckley,我发现了我的单行命令:(问题已解决)。

cut -d"$1" -f `shift; echo $* | sed 's/[^ 0-9]\{1,\}.*$//;s/[ ]$//;s/[ ]\{1,\}/,/g'` `shift; printf "%s\n" $(echo $*) | grep -v '^[0-9]$'`

这里 $* 是输入参数,如果上面将作为别名或函数在名为 say filterc 的 .rc 文件中,那么 synopsys 将是:

filterc delimiter column1 [column2 [column3...]] file1 [file2 [file3...]]  

地点:

分隔符 - 仅一个字符

column1..n - 代表列的数字

file1..n - 要过滤的文件,这里假设文件没有来自 仅数字,并且所有格式都相同。

【问题讨论】:

  • echo 和反向波浪号在 awk 中没有任何意义。你应该更好地解释你想要做什么?
  • 要将 shell 变量传递给awk,您需要使用-v 参数。见stackoverflow.com/questions/6373379/using-awk-with-variables
  • 测试你做了什么:echo '{print ...}'(血腥的语法高亮不让我写完整的代码)
  • 感谢大家的意见。看起来自己发现了问题所在: echo 在执行后添加了一个 \n ,导致行中断:} 不存在以关闭 awk 的语句。还必须进行一些调整才能最终使其正常工作 awk -F';' '{print '"echo '$3 \";\" $4 \";\"\c'"' }'
  • 在给定特定样本输入集的情况下产生所需输出的软件是寻找解决方案的起点。这不一定是一个好的解决方案。在这种情况下,您至少会接受不一致的回显实现,可能会扩展为导致奇怪错误的 awk 代码的参数,复杂的引用问题,潜在的通配符和分词问题等。当您使用时,这都是 100% 不必要的可以简单地向 awk 传递您要打印的字段的字符串,然后让它执行此操作。

标签: bash unix awk ksh


【解决方案1】:
function my_cmd {
    fs="$1"
    shift
    eval file="\$$#"
    awk -F"$fs" -v flds="$*" '
        BEGIN{ n=split(flds,f,/ /) }
        {
           for (i=1; i<n; i++)
               printf "%s%s", (i>1?FS:""), $(f[i])
           print ""
        }
    ' "$file"
}

$ cat file
a;b;c;d;e;f;g;h

$ my_cmd ';' 3 6 7 8 file                                                     
c;f;g;h

$ my_cmd ';' 6 3 8 file  
f;c;h

【讨论】:

  • 如果要提供多个文件作为输入,如何进行上述调整?
  • 在 awk 脚本上方添加代码以将文件名与非文件名分开。由于任何数字都可以是文件名,我不知道您打算如何将它们分开。
【解决方案2】:

你的命令听起来很像cut:

cut -d ';' -f 1,3 <<EOT
one;two;three
foo;bar;quux
EOT

one;three
foo;quux

cut -d '-' -f 2,4 <<EOT
one-two-three-four
five-six-seven-eight
EOT

two-four
six-eight

【讨论】:

  • 嘿,是的,这更可取(除非您正在处理 cut 不做的多字符分隔符),+1
【解决方案3】:

这就是你所追求的吗?

#!/bin/bash

get_columns()
{
    local fs=$1; shift
    local _awk=
    local column

    for column; do
        _awk="${_awk}\$${column},"
    done
    awk -F"$fs" -v OFS="$fs" "{ print ${_awk%,} }"
}

get_columns ';' 1 3 <<EOT
one;two;three
foo;bar;quux
EOT

get_columns '-' 2 4 <<EOT
one-two-three-four
five-six-seven-eight
EOT

-

$ ./t.sh
one;three
foo;quux
two-four
six-eight

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多