다음과 같은 파일이 있습니다.
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
레코드 구분 기호 regex를 지원하는 Awk가 있는 경우 RS
다음을 수행할 수 있습니다.
awk 'BEGIN { RS = " +| *\\\\?\\n" } 1'
이것의 장점은 전체 파일을 메모리에 넣지 않고 일부 정규식 대체를 수행하지 않고 입력 길이가 기가바이트가 될 수 있다는 것입니다.
우리는 기본적으로 파일을 두 개의 레코드 구분 기호로 처리합니다. 하나 이상의 공백 또는 0개 이상의 공백과 개행 문자 앞에 선택적 백슬래시가 올 수 있습니다.
이러한 방식으로 레코드를 분리한 경우 우리가 해야 할 일은 레코드를 출력하고 그 뒤에 기본 출력 레코드 구분 기호( ORS
)(물론 개행 문자)를 붙이는 것뿐입니다. 이는 다음으로 구성된 패턴 작업 규칙을 통해 달성됩니다 1
.
sed
또는 배관을 사용하고 tr
POSIX에 존재하지 않는 것을 사용하지 마십시오.
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