web-dev-qa-db-ja.com

シェルスクリプトでオプションの入力を処理する方法は?

私の割り当てタスクは、テキストファイルから最長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
3
amV

パイプラインは、単一の引数(返される行数)をとるスクリプトの一部であると想定しています。

パラメータ展開_${$1:-5}_は無効であり、_${1:-5}_が空であるか設定されていない場合に_5_に展開するには、_$1_と記述する必要があります。

また、awkコードはsortを呼び出しますが、これは特に、パイプラインに独自のステージとして簡単に挿入できるため、少し難読化されています。

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

少し単純化して(sedcutに置き換え)、出力をもう少し「表形式」にするために、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
_

これはrequires最初の引数は常に数値であることに注意してください(スクリプトにはbash固有のものがないため、インタープリターとして_/bin/sh_を使用します)。スクリプトに番号を付けるための適切なコマンドラインオプションを使用するには、たとえば、なので

_./script -n 10 file1 file2
_

コマンドライン解析を行うには、getoptsの使用を検討する必要があります。このサイトにはその例がたくさんあります( getopts タグを見ることから始めることができます)。

4
Kusalananda