
다음과 같은 파일이 있습니다.
Dir1/File1.cpp Dir2/File2.cpp \
Dir3/File1.h Dir4/File2.cpp \
Dir2/File1.cpp \
Dir2/File1.h \
다음과 같은 파일을 생성하고 싶습니다.
Dir1/File1.cpp
Dir2/File2.cpp
Dir3/File1.h
Dir4/File2.cpp
Dir2/File1.cpp
Dir2/File1.h
Bash/Sed/Awk/Grep 또는 이와 유사한 것을 사용하여 이를 수행하는 방법은 무엇입니까?
답변1
레코드 구분 기호에 대한 정규식을 지원하는 Awk가 있는 경우 RS
다음과 같이 수행할 수 있습니다.
awk 'BEGIN { RS = " +| *\\\\?\\n" } 1'
이것의 장점은 전체 파일을 메모리에 저장하지 않고 일부 정규식 대체를 수행하지 않는다는 것입니다. 입력 길이는 기가바이트일 수 있습니다.
우리는 기본적으로 파일을 두 개의 레코드 구분 기호로 처리합니다. 즉, 하나 이상의 공백 또는 0개 이상의 공백과 개행 문자(선택 사항 백슬래시 앞에 올 수 있음)가 뒤따르는 것입니다.
이런 방식으로 레코드를 구분한 후 우리가 해야 할 일은 레코드를 출력하고 그 뒤에 기본 출력 레코드 구분 기호( ORS
)(물론 개행 문자)가 오는 것입니다. 이는 다음으로 구성된 패턴-동작 규칙에 의해 달성됩니다 1
.
또는 POSIX에 없는 것을 사용하지 않고 sed
및 을 사용 하는 파이프라인 작업 :tr
tr '\n' ' ' | sed -e 's/\\//g' -e 's/ \+/ /g' | tr ' ' '\n'
줄 바꿈을 공백으로 바꾸십시오. 그런 다음 백슬래시를 제거하면서 여러 공백을 하나의 공백으로 스쿼시합니다. 그런 다음 공백을 개행 문자로 매핑합니다.
답변2
GNU와 함께grep
$ cat file
Dir1/File1.cpp Dir2/File2.cpp \
Dir3/File1.h Dir4/File2.cpp \
Dir2/File1.cpp \
Dir2/File1.h \
$ grep -o '[^\ ]*' file
Dir1/File1.cpp
Dir2/File2.cpp
Dir3/File1.h
Dir4/File2.cpp
Dir2/File1.cpp
Dir2/File1.h
-o
일치하는 패턴만 추출[^\ ]*
0개 이상의 비공백 및 비\
문자입니다.*
탐욕스럽기 때문에 가능한 한 많은 문자를 일치시키려고 시도합니다.
결과를 다른 파일에 저장하려면 다음을 사용하십시오.
$ grep -o '[^\ ]*' file > out_file
@Stéphane Chazelas가 지적했듯이 이식성을 높이기 위해 다음을 사용하는 것이 좋습니다.
grep -oE '[^\ ]+' file
여기서 -E
확장 정규식을 호출하고 공백 및 문자가 [^\ ]+
아닌 하나 이상과 일치합니다.\
성능 분석:
$ perl -ne 'print "$_"x100000' file > file_big
$ shuf file_big -o file_big
$ du -sh file_big
9.0M file_big
비교에 사용된 의견의 모든 답변 및 제안:
$ time grep -o '[^\ ]*' file_big > o1
real 0m2.090s
user 0m2.076s
sys 0m0.016s
$ time grep -oE '[^\ ]+' file_big > o2
real 0m1.523s
user 0m1.504s
sys 0m0.012s
$ time awk 'BEGIN { RS = " +| *\\\\?\\n" } 1' file_big > o3
real 0m0.331s
user 0m0.320s
sys 0m0.008s
$ time tr -s '\\ ' '[\n*]' < file_big | grep . > o4
real 0m0.095s
user 0m0.124s
sys 0m0.008s
$ time tr '\\ ' '[\n*]' < file_big | grep . > o5
real 0m0.105s
user 0m0.104s
sys 0m0.016s
위생 검사
$ diff -s o1 o2
Files o1 and o2 are identical
$ diff -s o1 o3
Files o1 and o3 are identical
$ diff -s o1 o4
Files o1 and o4 are identical
$ diff -s o1 o5
Files o1 and o5 are identical