したがって、すべての可能な状況を正しく処理することを確認するために、いくつかの機能に対して実行したいテストコマンドでいっぱいのファイルがあります。しかし、重複したコマンドを使用することは意味がありません。ここにいくつかの例があります。
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
'x'
大文字の前に小文字を追加する必要がある場合は、ASCIIでis 'X' ^ 32
(および'X'
is '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
要求に応じてすべての大文字オプションの前にすべての小文字オプションをソートする(おそらく最適ではないかもしれない)方法は次のとおりです。
$ 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
し、ループ後にその変数に対して操作を実行すると、冗長オプションに対する操作を複数回防止できます。