次のような簡単な要件があります。
絶対ディレクトリでファイル名を取得しています。
たとえば/home/parent/child/filename
私の要件は、これからファイル名をカットすることです。
私が試したのは:
awk -F "/" '{print $5}' input
完璧に機能します。
しかし、ここでは$5
をハードコーディングしています。これは、入力が次のような構造の場合は異なる場合があります。
/home/parent/child1/child2/filename
したがって、ハードコーディングなしで動的である必要があります。ロジックは次のとおりです。
常にファイル名となる最後のフィールドを使用します(逆から確認する必要があります)。
誰でもawk substr関数または他の関数で私を助けることができますか?
awk
は、ユーザーが定義できるフィールドセパレータに基づいてフィールド内の行を分割するという事実を使用します。したがって、フィールドセパレータを/
に定義すると、次のようになります。
awk -F "/" '{print $NF}' input
NF
は現在のレコードのフィールド数を指すため、$NF
の印刷は最後のフィールドの印刷を意味します。
したがって、次のようなファイルを指定します。
/home/parent/child1/child2/child3/filename
/home/parent/child1/child2/filename
/home/parent/child1/filename
これは出力になります:
$ awk -F"/" '{print $NF}' file
filename
filename
filename
この場合、basename
の代わりにawk
を使用することをお勧めします。
$ basename /home/parent/child1/child2/filename
filename
Perlソリューションを公開している場合は、fedorquiのawkソリューションに似ています。
Perl -F/ -lane 'print $F[-1]' input
-F/
は、フィールド区切り文字として/
を指定します$F[-1]
は、@F
自動分割配列の最後の要素です
別のオプションは、bash
パラメーター置換 を使用することです。
$ foo="/home/parent/child/filename"
$ echo ${foo##*/}
filename
$ foo="/home/parent/child/child2/filename"
$ echo ${foo##*/}
filename
それはベースネームの答えに対するコメントであるべきですが、私は十分なポイントを持っていません。
二重引用符を使用しない場合、basename
はスペース文字があるパスでは機能しません。
$ basename /home/foo/bar foo/bar.png
bar
引用符 ""で大丈夫
$ basename "/home/foo/bar foo/bar.png"
bar.png
ファイルの例
$ cat a
/home/parent/child 1/child 2/child 3/filename1
/home/parent/child 1/child2/filename2
/home/parent/child1/filename3
$ while read b ; do basename "$b" ; done < a
filename1
filename2
filename3
私はこれに3年遅れていることを知っていますが、...パラメータの拡張を検討する必要があります、それは組み込みで高速です。
入力がvarにある場合、たとえば$ var1で${var1##*/}
を実行します。下を見て
$ var1='/home/parent/child1/filename'
$ echo ${var1##*/}
filename
$ var1='/home/parent/child1/child2/filename'
$ echo ${var1##*/}
filename
$ var1='/home/parent/child1/child2/child3/filename'
$ echo ${var1##*/}
filename
5年後のように、私は、すべての提案のおかげで、次の方法でこれを行っていたことを知っています。
$ echo /home/parent/child1/child2/filename | rev | cut -d '/' -f1 | rev
filename
より良いマナーがあることに気付いてうれしい