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

mrzz3bfm  于 2023-03-15  发布在  其他
关注(0)|答案(3)|浏览(106)

新到这个网站:我有一个问题分析数据在一个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"
yh2wf1be

yh2wf1be1#

使用任意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"

以上假设您有理由打印16个单独的字段,而不是仅打印一个范围或所有字段或输入中某个点之后的字段或其他内容。
它还假设您要解决的问题是使用shell数组中的-v设置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"
pbwdgjma

pbwdgjma2#

我想解释一下为什么你的尝试失败了

-v terms="$xp_terms_columns"

我并不像你想的那样工作,请注意

arr=("Able" "Baker" "Charlie")
echo $arr

给出输出

Able
ecfsfe2w

ecfsfe2w3#

除非出于某种原因确实需要这些字段名,否则假设shell数组包含一堆要打印出来的列号,那么一个简单的子过程可以使工作变得容易得多:

xp_terms_columns=( $( jot 127 | rev | shuf | rev | head -n 16 ) )

echo "\n\t ${xp_terms_columns[*]} | ${#xp_terms_columns[*]}\n"

date | gawk -p- -be '

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, "= ", $'"$( 

      awk NF=NF OFS=', $' ORS= <<< "$xp_terms_columns[*]" 

                                           )"') }'
99 66 25 62 72 16 12 108 69 117 8 22 98 19 61 93 | 16
Tue Mar 14 23:27:03 EDT 2023 =                                                                                                                                                                          
    # gawk profile, created Tue Mar 14 23:27:03 2023

    # BEGIN rule(s)

    BEGIN {
     1      format = "%-8s %s %9s %9s %8s %10s %7s %10s %16s %14s %9s %11s %9s %9s %12s %7s %6s %7s\n"
    }

    # Rule(s)

     1  ($title_column ~ title) && ($source_column ~ _sourcefile) && ($source_column ~ box) { # 1
     1      printf format, $score, "= ", $99, $66, $25, $62, $72, $16, $12, $108, $69, $117, $8, $22, $98, $19, $61, $93
    }

从列号的shell数组动态生成一段干净的代码,而不必对它们大惊小怪

相关问题