通常在 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` 了。
沒有留言:
張貼留言