次の行を含むファイルがあります。
ファイル1
./filled/Event_repeatFILLED.svelte
./dir2/Miscellaneous_servicesFILLED.svelte
./outline/Line_weightFILLED.svelte
./two-tone/ArchitectureFILLED.svelte
...many more lines ...
基本名だけを含むファイルを作成したいと思います。
ファイル2
Event_repeatFILLED.svelte
Miscellaneous_servicesFILLED.svelte
Line_weightFILLED.svelte
ArchitectureFILLED.svelte
...
現在、以下は機能しません。
sed 's/^.\///' file1 > file2
Shell / Bashを使用してこれを行うにはどうすればよいですか?
答え1
sed 代替コマンドでは、異なる区切り文字を使用する必要があります。たとえば、
$ sed 's|.*/||' file
Event_repeatFILLED.svelte
Miscellaneous_servicesFILLED.svelte
Line_weightFILLED.svelte
ArchitectureFILLED.svelte
...many more lines ...
または:
$ perl -pe 's|.*/||' file
Event_repeatFILLED.svelte
Miscellaneous_servicesFILLED.svelte
Line_weightFILLED.svelte
ArchitectureFILLED.svelte
...many more lines ...
または以下を使用してawk
:
$ awk -F'/' '{print $NF}' file
Event_repeatFILLED.svelte
Miscellaneous_servicesFILLED.svelte
Line_weightFILLED.svelte
ArchitectureFILLED.svelte
...many more lines ...
それとも、次のような愚かなことがあります。
$ rev file | cut -d / -f 1 | rev
Event_repeatFILLED.svelte
Miscellaneous_servicesFILLED.svelte
Line_weightFILLED.svelte
ArchitectureFILLED.svelte
...many more lines ...
あるいは、コメントに提案されているように使用することもできますが、basename
これはより複雑で遅くなります。
$ while IFS= read -r fileName; do basename -- "$fileName"; done < file
Event_repeatFILLED.svelte
Miscellaneous_servicesFILLED.svelte
Line_weightFILLED.svelte
ArchitectureFILLED.svelte
最後に、本当に純粋なシェルソリューションが必要な場合は、次のようにすることができます。
$ while IFS= read -r fileName; do printf '%s\n' "${fileName##*/}"; done < file
Event_repeatFILLED.svelte
Miscellaneous_servicesFILLED.svelte
Line_weightFILLED.svelte
ArchitectureFILLED.svelte
...many more lines ...
ただし、最後の2つは使用しないでください。効率が最も低く複雑です。バラよりシェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか?。
答え2
xargs
とのGNU実装では、basename
次のことができます。
xargs -rd '\n' -a file1 basename -a -- > file2
使用の利点は、basename
またはなどの一部の特殊なケースを正しく処理できることです。/
/some/dir/
同等の操作は手動で行われます。
LC_ALL=C sed -e 's:^//*$:/:;t' -e 's:/*$::; s:.*/::' < file1 > file2
LC_ALL=C
ファイルパスがロケールの有効なテキストで構成されるという保証がないため、必要です。/
または//
、///
...特別処理- 末尾が
/
削除されました。 - 次に、右端のすべての項目を削除します
/
。
を使用している場合は、(for ail)修飾子(から借り)をzsh
使用することもできます。:t
t
csh
print -rC1 -- ${${(f)"$(<file1)"}:t} > file2
/
(または//
、...)の場合は、代わりに空の文字列を返すという点で///
GNUとは異なります。basename
/
そしてperl
:
perl -MFile::Basename -lpe '$_=basename$_' < file1 > file2
答え3
あまり深く入らず、コマンドに関する即時の質問は、ポイントが「すべて」を意味するものであることです。一つ正規表現の「文字」です。必要な数の文字を一致させる必要があります.*
(標準正規表現ではできるだけ多く)。
だから試してみてください
sed 's/^.*\///' file1 > file2
他の回答やコメントに記載されている注意事項が適用されます。