
そこで、いくつかの関数に対して実行して、考えられるすべての状況を正しく処理しているかどうかを確認するテスト コマンドが満載のファイルを用意しました。ただし、コマンドが重複しても意味がありません。次に例を示します。
rap ,Xflg MIT X11
rap ,XPBfl 'MITER'
rap ,Bflg share git-grep
rap ,bfl X11
rap ,Bfl xzfgrep
rap ,Bf X11
... 私の関数 'rap' は、文字オプションの開始を示すためにダッシュではなくコンマを使用し、その後に引数が続きます。これらのオプションの順序は重要ではありません。
rap ,Bf X11
rap ,fB X11
... はまったく同じコマンドです。もちろん、ファイルから重複行を削除するのは簡単ですが、上記の問題を回避するには、オプションをアルファベット順に並べ替えて、上記のようにすることが望まれます。
rap ,Bf X11
rap ,Bf X11
... そして重複を削除できるようになります。ヒロイックなしでもそのようなことはできますか? これはオプションのリストで並べ替えるのではなく、オプション自体を並べ替えることに注意してください。
答え1
別のperl
バリエーション:
$ perl -pe 's{^rap ,\K\S+}{join "", sort split //, $&}e' file
rap ,Xfgl MIT X11
rap ,BPXfl 'MITER'
rap ,Bfgl share git-grep
rap ,bfl X11
rap ,Bfl xzfgrep
rap ,Bf X11
小文字を大文字の前に置かなければならないという追加の要件については、ASCII では で'x'
ある'X' ^ 32
(および で'X'
ある'x' ^ 32
) という事実に頼ることができます。
$ perl -pe 's{^rap ,\K\S+}{join "", sort {(ord($a)^32) <=> (ord($b)^32)} split //, $&}e' file
rap ,fglX MIT X11
rap ,flBPX 'MITER'
rap ,fglB share git-grep
rap ,bfl X11
rap ,flB xzfgrep
rap ,fB X11
答え2
Perl を使用して、コンマに続く単語の文字のシーケンスを取得し、その結果を配列に分割し、それをソートして結果を置き換えることができます。
$ perl -pe 's{(?<=,)(\w+)}{join "", sort split(//, $1)}e' yourfile
rap ,Xfgl MIT X11
rap ,BPXfl 'MITER'
rap ,Bfgl share git-grep
rap ,bfl X11
rap ,Bfl xzfgrep
rap ,Bf X11
ご要望に応じて、すべての小文字オプションを大文字オプションの前に並べ替える 1 つの方法 (おそらく最適ではない) を次に示します。
$ perl -pe 's{(?<=,)(\w+)}{@opts = split(//,$1); join "",
(sort grep /[[:lower:]]/,@opts), (sort grep /[^[:lower:]]/, @opts)
}e' yourfile
rap ,fglX MIT X11
rap ,flBPX 'MITER'
rap ,fglB share git-grep
rap ,bfl X11
rap ,flB xzfgrep
rap ,fB X11
答え3
GNU awkを使用してsorted_in
いずれにせよgawkを使用するので、他にも便利だが不要な拡張機能をいくつか使用して、装飾-並べ替え-装飾解除の慣用句1
小文字の前に を置き、2
大文字の前に を置くと、小文字がすべて大文字より前にソートされ、印刷前にそれらの装飾が再度削除されます。
$ cat tst.awk
BEGIN { PROCINFO["sorted_in"] = "@val_str_asc" }
match( $0, /^(\s*\S+\s*,)(\S+)(.*)/, a ) {
gsub( /[[:lower:]]/, "1 &,", a[2] ) # Decorate
gsub( /[[:upper:]]/, "2 &,", a[2] )
sorted = ""
split(a[2],opts,",")
for ( idx in opts ) { # Sort
sorted = sorted opts[idx]
}
gsub( /[[:digit:] ,]/, "", sorted ) # Undecorate
$0 = a[1] sorted a[3]
}
{ print }
$ awk -f tst.awk file
rap ,fglX MIT X11
rap ,flBPX 'MITER'
rap ,fglB share git-grep
rap ,bfl X11
rap ,flB xzfgrep
rap ,fB X11
答え4
入力ファイル内のカンマをダッシュに置き換えると、getopts
通常どおりを使用してrap
関数のオプションを解析できます。
この変更は を使用して行うことができ、行の先頭を にsed
変更するだけでよいと仮定すると、次のようになります。rap ,
rap -
sed 's/^rap ,/rap -/' file.in >file
その後、関数が以前に宣言されていると. ./file
仮定して、生成されたファイルをスクリプト内で簡単にソース化できるようになります。rap
関数内のオプションを解析するにはrap
:
rap () {
OPTIND=1
unset -v B_flag P_flag X_flag
unset -v b_flag f_flag g_flag l_flag
while getopts BPXbfgl opt; do
case $opt in
B) B_flag=true ;;
P) P_flag=true ;;
X) X_flag=true ;;
b) b_flag=true ;;
f) f_flag=true ;;
g) g_flag=true ;;
l) l_flag=true ;;
*) echo 'Error' >&2; return 1
esac
done
shift "$(( OPTIND - 1 ))"
# Act on set flags here.
if "${f_flag-false}"; then
echo 'The -f option was used'
fi
# The non-options are available in "$@".
printf 'Other argument: %s\n' "$@"
printf -- '---\n'
}
ループ内でフラグ変数を設定しwhile
、ループ後にそれらを操作すると、重複したオプションが複数回操作されることが回避されることに注意してください。