通常在 GNU/Linux 系統底下使用 command 時都會有帶一些額外的參數,像是以下的例子:
$ echo `seq 0 9` | xargs -n1 | wc -l
利用 `seq 0 9` 產生出 0 到 9 的數字,然後 echo 輸出,再用 xargs -n1 利用空白分開每個數字插入換行符號,然後再導到 wc -l 去計算行數。(其實寫成 `seq 0 9 | wc -l` 也有同樣的效果,利用 hexdump -C 就可以看出其中的不同)
其中的 wc -l 也可以寫成 wc --lines 這樣更清楚、更容易理解。
如果說我們想要利用 Bash shell 寫一個同樣的功能,就可以寫成下面這樣:
#!/bin/bash
while getopts l name; do
case "$name" in
('l')
line=1
;;
esac
shift
done
if [ -n "$line" ]; then
awk 'END { print NR }' "$@"
fi
跟原本的 wc -l 提功同樣功能只是換成使用 awk 這個指令來計算行數。
然而 Bash 內建的 getopts 無法直接提供 --lines 這樣的使用方式,於是就可以改用外部的 getopt 指令來達成。
#!/bin/bash
set -e
eval set -- $(getopt -o l -l "lines" -- "$@")
set +e
while :; do
case "$1" in
('-l'|'--lines')
line=1
;;
('--')
shift
break
;;
esac
shift
done
if [ -n "$line" ]; then
awk 'END { print NR }' "$@"
fi
如果說要利用 Bash 內建的 getopts 寫一個 xargs -n1 這樣的功能,則可以寫成以下這樣:
#!/bin/bash
while getopts n: name; do
case "$name" in
('n')
max="$OPTARG"
;;
esac
[ "$OPTIND" = 2 ] && shift
[ "$OPTIND" = 3 ] && shift 2
done
if [ -n "$max" ]; then
awk "{for (i = 1 ; i <= NF ; i++) { if (i % $max == 0) printf \"%s\\n\", i; else printf \"%s \", i } }" "$@"
fi
如果要支援 xargs --max-lines=1 這樣的使用方式,則可以利用外部的 getopt 改寫成以下這樣:
#!/bin/bash
# filename: xargs.sh
set -e
eval set -- $(getopt -o "n:" -l "max-lines:" -- "$@")
set +e
while :; do
case "$1" in
('-n'|'--max-lines')
max="$2"
shift 2
;;
('--')
shift
break
;;
esac
done
if [ -n "$max" ]; then
awk "{for (i = 1 ; i <= NF ; i++) { if (i % $max == 0) printf \"%s\\n\", i; else printf \"%s \", i } }" "$@"
fi
這樣就可以使用 `xargs.sh --max-lines=1` 了。