다음 줄이 포함된 파일이 있습니다.
파일 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
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
다른 답변과 의견에 언급된 주의 사항이 적용됩니다.