如何将命令行 awk 脚本(带参数)作为 bash 脚本运行?

时间:2021-01-28 20:10:11

标签: bash awk

我有一个 awk 脚本 (tst.awk):

NR==FNR {
    ids[++numIds] = $1","
    next
}
FNR==1 { numFiles++ }
{
    id = $1
    sub(/^[^[:space:]]+[[:space:]]+/,"")
    vals[id,numFiles] = $0
    gsub(/[^[:space:],]+/,"NA")
    naVal[numFiles] = $0
}
END {
    for ( idNr=1; idNr<=numIds; idNr++) {
        id = ids[idNr]
        printf "%s%s", id, OFS
        for (fileNr=1; fileNr<=numFiles; fileNr++) {
            val = ((id,fileNr) in vals ? vals[id,fileNr] : naVal[fileNr])
            printf "%s%s", val, (fileNr<numFiles ? OFS : ORS)
        }
    }
}

在命令行上调用:

awk -f tst.awk master file1 file2 file3 > output.file

(注意:可以有可变数量的参数)

如何更改此脚本和命令行代码以将其作为 bash 脚本运行?

我已经尝试过 (tst_awk.sh):

#!/bin/bash

awk -f "$1" "$2" "$3" "$4"

'NR==FNR {
        ids[++numIds] = $1","
        next
    }
    FNR==1 { numFiles++ }
    {
        id = $1
        sub(/^[^[:space:]]+[[:space:]]+/,"")
        vals[id,numFiles] = $0
        gsub(/[^[:space:],]+/,"NA")
        naVal[numFiles] = $0
    }
    END {
        for ( idNr=1; idNr<=numIds; idNr++) {
            id = ids[idNr]
            printf "%s%s", id, OFS
            for (fileNr=1; fileNr<=numFiles; fileNr++) {
                val = ((id,fileNr) in vals ? vals[id,fileNr] : naVal[fileNr])
                printf "%s%s", val, (fileNr<numFiles ? OFS : ORS)
            }
        }
    }' > output_file

在命令行上调用:

./tst_awk.sh master file1 file2 file3

我也试过(tst_awk2.sh):

#!/bin/bash

awk -f master file1 file2 file3

'NR==FNR {
        ids[++numIds] = $1","
        next
    }
    FNR==1 { numFiles++ }



...

        }
    }
}' > output_file

在命令行上调用:

./tst_awk2.sh

2 个答案:

答案 0 :(得分:2)

-f 后面需要跟 awk 脚本的名称。您将 shell 脚本的第一个参数放在它之后。

您可以使用 "$@" 获取所有脚本参数,因此您不仅限于 4 个参数。

#!/bin/bash

awk -f /path/to/tst.awk "$@" > output_file

使用 awk 脚本的绝对路径,以便您可以从任何目录运行 shell 脚本。

如果您不想使用单独的 tst.awk,您只需将脚本作为文字第一个参数放入 awk

#!/bin/bash

awk 'NR==FNR {
        ids[++numIds] = $1","
        next
    }
    FNR==1 { numFiles++ }
    {
        id = $1
        sub(/^[^[:space:]]+[[:space:]]+/,"")
        vals[id,numFiles] = $0
        gsub(/[^[:space:],]+/,"NA")
        naVal[numFiles] = $0
    }
    END {
        for ( idNr=1; idNr<=numIds; idNr++) {
            id = ids[idNr]
            printf "%s%s", id, OFS
            for (fileNr=1; fileNr<=numFiles; fileNr++) {
                val = ((id,fileNr) in vals ? vals[id,fileNr] : naVal[fileNr])
                printf "%s%s", val, (fileNr<numFiles ? OFS : ORS)
            }
        }
    }' "$@" > output_file

答案 1 :(得分:0)

您可以通过添加 shebang 使您的 awk 脚本可执行

#! /bin/awk -f

NR==FNR {
   ids[++numIds] = $1","
   next
}...

不要忘记chmod +x tst.awk 并运行

$ ./tst.awk  master file1 file2 file3 > outfile