Bash
如何正確辨識參數的順序?
這是我的任務。任務是從輸入文件中輸出 n 行最長的行。如果 n 沒有參數,則 n 的預設值為 5。如果參數中沒有文件,則使用標準輸入。如果至少有 2 個文件,則輸出名稱文件。輸出行的順序應與原始文件中的順序相同。我在這裡問了一個問題來處理可選參數:如何處理 shell 腳本中的可選輸入?
但是,我遇到了新的 shell 腳本的另一個問題。
#!/bin/sh while getopts “n” arg; do case $arg in n) # Check next positional parameter eval nextopt=\${$OPTIND} # existing or starting with dash? if [[ -n $nextopt && $nextopt != -* ]] ; then OPTIND=$((OPTIND + 1)) level=$nextopt else level=5 fi ;; esac done for name do if [ "$#" -gt 1 ]; then printf 'File: %s\n' "$name" fi awk '{ print length(), NR, $0 | "sort -rn" }' $name | head -n $level | sed 's/[^ ]* //' | sort -n done
我這樣執行
sh ex1.sh -n 10 unix1.txt unix1.1.txt
這是輸出
File: -n awk: can't open file -n source line number 1 File: 10 awk: can't open file 10 source line number 1 File: unix1.txt 2 kbjkbkbbnbnmbnmnmmnbmnbmjbjkb 3 asjdsakdbakjsdbasbkj 4 asjdsakdbakjsdbasbkj 5 asjdsakdbakjsdbasbkj 10 ppûunsdj 11 tieutuvi 13 sdbhsdbjhdsvfdsvfgj 14 avavdvas 16 ffdsdfggdgdgdfgdfgdf112233 17 qwertyuiopsdfghjklxcvbnm,fghjk File: unix1.1.txt 1 csdkbfsdk 2 fskjfnjkfnkjdsndjks 3 fsnjfnsjkf 4 snjfndsjknskjdfbnjksfdsfn 5 323124 6 jknjkkjnk4n4jn2 7 kjnjkb423 13 423b2j3kb4jk23bkb234kb32 14 234jb32jk43b 15 331
“-n”和“10”不是文件。另外,如果我這樣跑
sh ex1.sh -n unix1.txt unix1.1.txt
輸出應該是文件中最長的 5 行,而是:
File: -n head: illegal line count -- unix1.txt awk: can't open file -n source line number 1 File: unix1.txt head: illegal line count -- unix1.txt File: unix1.1.txt head: illegal line count -- unix1.txt
那麼我該如何解決這個問題呢?雖然這不是目標,但這會奏效
while getopts “n” arg; do case $arg in n) # Check next positional parameter eval nextopt=\${$OPTIND} # existing or starting with dash? if [[ -n $nextopt && $nextopt != -* ]] ; then OPTIND=$((OPTIND + 1)) level=$nextopt else level=5 fi ;; esac done awk '{ print length(), NR, $0 | "sort -rn" }' unix1.txt | head -n $level | sed 's/[^ ]* //' | sort -n
如果我跑
sh ex1.sh -n
我有
2 kbjkbkbbnbnmbnmnmmnbmnbmjbjkb 4 asjdsakdbakjsdbasbkj 5 asjdsakdbakjsdbasbkj 16 ffdsdfggdgdgdfgdfgdf112233 17 qwertyuiopsdfghjklxcvbnm,fghjk
或者
sh ex1.sh -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
選項需要一個參數,因此您需要getopts 'n:' arg
.選項參數位於
$OPTARG
.不要
OPTIND
在while getopts
循環中觸摸。循環之後,
shift "$(( OPTIND - 1 ))"
. 這會將文件名留在位置參數中。那是,
#!/bin/sh level=5 while getopts 'n:' arg; do case $arg in n) level=$OPTARG ;; *) echo 'Error in command line parsing' >&2 esac done shift "$(( OPTIND - 1 ))" for name do # stuff done
接下來,您永遠不會處理沒有輸入文件的情況。
如果沒有給出,以下使腳本使用標準輸入作為文件名:
if [ "$#" -eq 0 ]; then # handle no filenames, for example: set -- /dev/stdin fi for name do # stuff done
我將把剩下的留給你(但為了清楚起見,我強烈建議將其
sort
移出awk
並將其作為管道中的自己的階段執行)。