如何处理shell脚本中的可选输入?

如何处理shell脚本中的可选输入?

我的作业任务是打印文本文件中最长的 n 行。输出是最长的 n 行,带有行号,并且顺序与原始文件中的顺序相同。例如,在原始文件中:

09876543
kbjkbkbbnbnmbnmnmmnbmnbmjbjkb
asjdsakdbakjsdbasbkj
asjdsakdbakjsdbasbkj
asjdsakdbakjsdbasbkj
sa
aaaa
njkasn
k
ppûunsdj
tieutuvi
eee
sdbhsdbjhdsvfdsvfgj
avavdvas
dfsdf
ffdsdfggdgdgdfgdfgdf112233
qwertyuiopsdfghjklxcvbnm,fghjk

如果 n 为 10,则输出应为

2 kbjkbkbbnbnmbnmnmmnbmnbmjbjkb
3 asjdsakdbakjsdbasbkj
4 asjdsakdbakjsdbasbkj
5 asjdsakdbakjsdbasbkj
10 ppûunsdj
11 tieutuvi
13 sdbhsdbjhdsvfdsvfgj
14 avavdvas
16 ffdsdfggdgdgdfgdfgdf112233
17 qwertyuiopsdfghjklxcvbnm,fghjk

如果未分配 n,则默认数量为 5。如果至少有 2 个输入文件,则每个行列表前面都有相应的文件名。我怎样才能做到这一点?我该如何处理参数n?例如,如果必须输入参数n,则此代码将起作用

awk '{ print length(), NR, $0 | "sort -rn" }' unix1.txt | head -n 10 | sed 's/[^ ]* //' | sort -n

但如果 n 是可选参数,则这不起作用。我也不知道如何处理很多文件。

awk '{ print length(), NR, $0 | "sort -rn" }' unix1.txt | head -n ${$1:-5} | sed 's/[^ ]* //' | sort -n >> temp.txt

答案1

我假设您的管道是采用单个参数(要返回的行数)的脚本的一部分。

参数扩展${$1:-5}无效,应编写为${1:-5}使其扩展为5if$1为空或未设置。

此外,您的awk代码调用sort有点混乱,特别是因为它可以很容易地作为自己的阶段插入管道中:

awk '{ print length(), NR, $0 }' unix1.txt | 
sort -rn |
head -n "${1:-5}" |
sed 's/[^ ]* //' |
sort -n

为了稍微简化一下(替换sedwith cut)并使输出更加“表格化”,我们可以使用制表awk符作为输出分隔符输出中间结果:

awk -v OFS="\t" '{ print length(), NR, $0 }' unix1.txt | 
sort -rn |
head -n ${1:-5} |
cut -f 2- |
sort -n

对于给定的数据,这将输出以下默认输出行数:

2       kbjkbkbbnbnmbnmnmmnbmnbmjbjkb
4       asjdsakdbakjsdbasbkj
5       asjdsakdbakjsdbasbkj
16      ffdsdfggdgdgdfgdfgdf112233
17      qwertyuiopsdfghjklxcvbnm,fghjk

要处理脚本中的多个文件,我建议循环遍历给定的文件名。也许像

#!/bin/sh

n=${1:-5}
shift

for name do
    if [ "$#" -gt 1 ]; then
        printf 'File: %s\n' "$name"
    fi

    awk -v OFS="\t" '{ print length(), NR, $0 }' "$name" | 
    sort -rn |
    head -n "$n"
    cut -f 2- |
    sort -n
done

该脚本将被调用为

./script.sh 10 file1 file2 file3 etc

请注意,这需要bash第一个参数始终是一个数字(并且脚本中没有任何特定内容,这就是我用作/bin/sh解释器的原因)。使用正确的命令行选项为脚本提供编号,例如

./script -n 10 file1 file2

你必须考虑使用getopts命令行解析。这个网站上有很多这样的例子(你可以先看看标签)。

相关内容