我的作业任务是打印文本文件中最长的 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}
使其扩展为5
if$1
为空或未设置。
此外,您的awk
代码调用sort
有点混乱,特别是因为它可以很容易地作为自己的阶段插入管道中:
awk '{ print length(), NR, $0 }' unix1.txt |
sort -rn |
head -n "${1:-5}" |
sed 's/[^ ]* //' |
sort -n
为了稍微简化一下(替换sed
with 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
命令行解析。这个网站上有很多这样的例子(你可以先看看获取选择标签)。