Bash awk ~ 如何向 awk 提供要打印的字段列表?

Gio*_*le 3 csv sorting bash awk

刚接触此网站:我在分析 csv 文件中的数据时遇到问题。

我编写了一个小脚本,用于从 csv 文件读取输入并仅打印所需的字段:

awk -F, -v _sourcefile=$i -v title="\"${k}\"" -v box="_${j}_" -v score="$dock_score_column" -v hbond="${xp_terms_columns[0]}" -v electro="${xp_terms_columns[1]}" -v phoben="${xp_terms_col umns[2]}" -v phobenhb="${xp_terms_columns[3]}" -v lowmw="${xp_terms_columns[4]}" -v rotpenal="${xp_terms_columns[5]}" -v lipophilicevdw="${xp_terms_columns[6]}" -v phobenpairhb="${xp_terms_columns[7]}" -v sitemap="${xp_terms_columns[8]}" -v penalties="${xp_terms_columns[9]}" -v pistack="${xp_terms_columns[10]}" -v hbpenal="${xp_terms_columns[11]}" -v expospenal="${xp_terms_columns[12]}" -v picat="${xp_terms_columns[13]}" -v clbr="${xp_terms_columns[14]}" -v zpotr="${xp_terms_columns[15]}"
'BEGIN{format = "%-8s %s %9s %9s %8s %10s %7s %10s %16s %14s %9s %11s %9s %9s %12s %7s %6s %7s\n"} $title_column ~ title && $source_column ~ _sourcefile && $source_column ~ box
{printf format, $score,"= ", $hbond, $electro, $phoben, $phobenhb, $lowmw, $rotpenal, $lipophilicevdw, $phobenpairhb, $sitemap, $penalties, $pistack, $hbpena l, $expospenal, $picat, $clbr, $zpotr}' $file


这是一团糟,但现在它做了我需要做的事情。
问题是:如何通过向其提供存储在其中的字段来使其变得更简单?{xptermscolumns[@]}

该文件是普通的 csv 文件,awk 脚本的第一部分只是查找要打印的正确记录,我唯一的问题是我必须声明要打印的 16 个不同变量。

我尝试过在 awk 中使用数组,例如:

awk -F, -v _sourcefile=$i -v title="\"${k}\"" -v box="_${j}_" -v terms="$xp_terms_columns" 'BEGIN{split(terms, array, " ")} $title_column ~ title && $source_column ~ _sourcefile && $sour ce_column ~ box { n=asorti(array, sorted); for (i=1;i<=n;i++) printf " " $sorted[i] }' $file

但没有成功,因为我无法让 asorti 以正确的顺序打印字段。


这是上面清晰地写的第一个脚本,以帮助解决这个问题,并作为 OP 将来遵循的示例:

awk -F,                                         \
    -v _sourcefile="$i"                         \
    -v title="\"${k}\""                         \
    -v box="_${j}_"                             \
    -v score="$dock_score_column"               \
    -v hbond="${xp_terms_columns[0]}"           \
    -v electro="${xp_terms_columns[1]}"         \
    -v phoben="${xp_terms_columns[2]}"          \
    -v phobenhb="${xp_terms_columns[3]}"        \
    -v lowmw="${xp_terms_columns[4]}"           \
    -v rotpenal="${xp_terms_columns[5]}"        \
    -v lipophilicevdw="${xp_terms_columns[6]}"  \
    -v phobenpairhb="${xp_terms_columns[7]}"    \
    -v sitemap="${xp_terms_columns[8]}"         \
    -v penalties="${xp_terms_columns[9]}"       \
    -v pistack="${xp_terms_columns[10]}"        \
    -v hbpenal="${xp_terms_columns[11]}"        \
    -v expospenal="${xp_terms_columns[12]}"     \
    -v picat="${xp_terms_columns[13]}"          \
    -v clbr="${xp_terms_columns[14]}"           \
    -v zpotr="${xp_terms_columns[15]}"          \
'
    BEGIN {
        format = "%-8s %s %9s %9s %8s %10s %7s %10s %16s %14s %9s %11s %9s %9s %12s %7s %6s %7s\n"
    }
    ($title_column ~ title) && ($source_column ~ _sourcefile) && ($source_column ~ box) {
        printf format, $score, "= ", $hbond, $electro, $phoben, $phobenhb, $lowmw,              \
                        $rotpenal, $lipophilicevdw, $phobenpairhb, $sitemap, $penalties,        \
                        $pistack, $hbpenal, $expospenal, $picat, $clbr, $zpotr
    }
' "$file"
Run Code Online (Sandbox Code Playgroud)

Ed *_*ton 7

使用任何 awk 尝试这个(未经测试):

awk -F,                                         \
    -v _sourcefile="$i"                         \
    -v title="\"${k}\""                         \
    -v box="_${j}_"                             \
    -v score="$dock_score_column"               \
    -v xp_terms_columns="${xp_terms_columns[*]}" \
'
    BEGIN {
        split(xp_terms_columns,xp," ")
        hbond           = xp[1]
        electro         = xp[2]
        phoben          = xp[3]
        phobenhb        = xp[4]
        lowmw           = xp[5]
        rotpenal        = xp[6]
        lipophilicevdw  = xp[7]
        phobenpairhb    = xp[8]
        sitemap         = xp[9]
        penalties       = xp[10]
        pistack         = xp[11]
        hbpenal         = xp[12]
        expospenal      = xp[13]
        picat           = xp[14]
        clbr            = xp[15]
        zpotr           = xp[16]

        format = "%-8s %s %9s %9s %8s %10s %7s %10s %16s %14s %9s %11s %9s %9s %12s %7s %6s %7s\n"
    }
    ($title_column ~ title) && ($source_column ~ _sourcefile) && ($source_column ~ box) {
        printf format, $score, "= ", $hbond, $electro, $phoben, $phobenhb, $lowmw,              \
                        $rotpenal, $lipophilicevdw, $phobenpairhb, $sitemap, $penalties,        \
                        $pistack, $hbpenal, $expospenal, $picat, $clbr, $zpotr
    }
' "$file"
Run Code Online (Sandbox Code Playgroud)

上面假设您有某种原因需要打印 16 个单独的字段,而不是仅打印一个范围或所有字段或输入中某个点之后的字段或其他字段。

它还假设您要解决的问题是-v从 shell 数组中设置 16 个 awk 变量,而不是使用 16 个 awk 变量。

这实际上可能就是您所需要的(再次未经测试):

awk -F,                                         \
    -v _sourcefile="$i"                         \
    -v title="\"${k}\""                         \
    -v box="_${j}_"                             \
    -v score="$dock_score_column"               \
    -v xp_terms_columns="${xp_terms_columns[*]}" \
'
    BEGIN {
        nxp  = split(xp_terms_columns,xp," ")
        nfmt = split("%-8s %s %9s %9s %8s %10s %7s %10s %16s %14s %9s %11s %9s %9s %12s %7s %6s %7s",fmt," ")
        if ( nxp != nfmt ) {
            print "field vs format count mismatch" | "cat>&2"
            exit 1
        }
    }
    ($title_column ~ title) && ($source_column ~ _sourcefile) && ($source_column ~ box) {
        printf "%-8s =", $score
        for ( i=1; i<=nxp; i++ ) {
            printf ("%s" fmt[i]), OFS, $(xp[i])
        }
        print ""
    }
' "$file"
Run Code Online (Sandbox Code Playgroud)