bash変数置換を使用して区切り文字に基づいて変数の一部を抽出できますか?ファイル名の直接ディレクトリ名を取得しようとしています(この場合foo
)。
$ filename=./foo/bar/baz.xml
私は私が次のことをすることができることを知っています。
echo $filename | cut -d '/' -f 2
または
echo $filename | awk -F '/' '{print $2}'
awk
ただし、ブランチ/cut
複数のファイル名は非常に遅くなります。
実際のファイルを使用して、さまざまなソリューションの分析を行いました。
エコ|カット:
real 2m56.805s
user 0m37.009s
sys 1m26.067s
エコ
real 2m56.282s
user 0m38.157s
sys 1m31.016s
@steeldriverの変数置換/シェルパラメータ拡張:
real 0m0.660s
user 0m0.421s
sys 0m0.235s
@jai_sのIFS引数:
real 1m26.243s
user 0m13.751s
sys 0m28.969s
どちらの提案も既存のアイデアに比べて大幅に改善されていますが、新しいプロセスをフォークする必要がないため、変数の置き換えが最も高速です。
答え1
一致の最も短い先行部分文字列を削除できます。*/
tmp="${filename#*/}"
次に、一致する最も長い末尾の部分文字列を削除します。/*
echo "${tmp%%/*}"
答え2
echo $f
a/b/c
$ (IFS='/';set $f; echo $1)
a
$ (IFS='/';set $f; echo $2)
b
$ (IFS='/';set $f; echo $3)
c
ワイルドカードを使用すると、二重引用符または一重引用符で動作するようです。
f="a?b?c"
$(IFS="?"; set $f; echo $1)
a
echo $f
a*b*c
(IFS="*"; set $f; echo $1)
a
はい、IFSをデフォルト値に復元する必要があります。
unset IFS
答え3
作業速度を上げるには、リストをフィードしてくださいawk
。
awk -F '/' '{print $2}' < <(find /usr)
awk -F '/' '{print $2}' < inputfile
デモ:
time awk -F '/' '{print $2; SUM++} END {print "number of directories found: " SUM}' < <(find /usr -type d)
usr
usr
.
.
number of directories found: 16748
real 0m8.910s
user 0m0.050s
sys 0m0.050s
答え4
awk/sed/cut の代わりに "dirname" コマンドを使用するとどうなりますか?
filename=./foo/bar/baz.xml
dirname $filename
生産する:
./foo/bar