フォルダがあり、その中でls
を実行すると、出力されます
t-1-myFirstTest.c
myFile.c
t-42-my_second_test.c
t-3-test1234.c
.
.
.
mySecondFile.c
t-21-tset241.c
改行とt-
と2番目の-
の間の数字を除いて、このテキストのすべてを削除したいと思います。したがって、この前の出力は次のようになります。
1
42
3
.
.
.
21
私には解決策がありますが、それは本当に悪いと思います。私たちが話しているフォルダーが実際には現在のディレクトリにある場合、私は
ls | grep -o -E t-[0-9]+-[a-zA-Z0-9_]+.c | grep -o -E t-[0-9]+ | grep -o -E [0-9]+
同じことを達成するためのより良い方法はありますか?
ls
の出力を解析することは悪い考えです(ls
の出力は厳密に見るためのものです)。詳細については、質問「 なぜ `ls`を解析しない*のですか? "」を参照してください。
これは、/bin/sh
でそれを行う方法です。
for filename in t-*-*.c; do
[ ! -f "$filename" ] && continue
number=${filename#t-} # remove "t-" from start of filename
number=${number%%-*} # remove everything from first "-" in what remains
printf '%s\n' "$number"
done
これは、名前がパターンt-*-*.c
に一致する現在のディレクトリ内のすべてのファイル名を反復します。これらの名前のそれぞれについて、t-
ビットが最初から削除され、次に2番目の-
とその後のすべてが、別のパラメーター展開で削除されます。
展開${variable#Word}
は、$variable
のstartからWord
の(最短の)一致を削除しますが、 ${variable%%Word}
は、文字列のendからWord
の(最長の)一致を削除します。
bash
では、ファイル名に正規表現の一致を使用します。
for filename in t-*-*.c; do
[ ! -f "$filename" ] && continue
if [[ "$filename" =~ ^t-([0-9]+)- ]]; then
printf '%s\n' "${BASH_REMATCH[1]}"
fi
done
これは、各ファイル名のt-
の後の数字と一致してキャプチャします。キャプチャされた数字のグループは、一致が成功した後、${BASH_REMATCH[1]}
で使用できます。インデックス1
は、正規表現の最初のキャプチャグループ(括弧)を参照します。
遅いが、おそらく快適な(「使い慣れた」のような)ソリューションの場合、外部コマンドを呼び出して、関心のある文字列のビットを解析することをお勧めします。
for filename in t-*-*.c; do
[ ! -f "$filename" ] && continue
cut -d '-' -f 2 <<<"$filename"
done
これはbash
を想定しており、ループでcut
を呼び出しても問題ないことを前提としています。これは、シェル自体に組み込まれた操作を使用するよりもはるかに遅くなります。ここでのcut
コマンドは、bash
から渡された文字列から2番目の-
-区切りフィールドを返すように求められます(「here-string」リダイレクトを使用)。
あなたの出力によると:
ls|awk -F"-" '{print $2}'
動作するはずですが、考慮したい場合はt-
一部の場合
ls|grep ^t-|awk -F"-" '{print $2}'
または
ls|awk -F"t-" '{print $2}'|awk -F"-" '{print $1}'
あなたの例からファイルのリストを作成したとき、私のls
はそれらを次のようにソートします。
$ ls -1
myFile.c
mySecondFile.c
t-1-myFirstTest.c
t-21-tset241.c
t-3-test1234.c
t-42-my_second_test.c
その結果、以下のbash関数は、ファイルの改行と番号を同じ順序で出力します。
改行とt-と2番目の間の数字を除いてこのテキストをすべて削除したい-
これは、t-
に一致しないファイル名は「改行を除いて削除する」必要があることを意味すると解釈しました。つまり、これらのファイル名には空白行を出力しますが、それ以外の場合はダッシュ間の数字を出力します。
lsnums ()
{
for f in *
do
if [[ "$f" =~ t-([[:digit:]]+)- ]]; then
printf '%s\n' "${BASH_REMATCH[1]}"
else
echo
fi
done
}
結果の出力は次のとおりです。
$ lsnums
1
21
3
42
... 2つの空白行は、t-
ではなくmy
で始まる最初のタイプのファイルに対応しています。
それは簡単に行うことができます:
ls | cut -d '-' -f 2