bash
변수의 파일 경로를 사용하여 스크립트에서 여러 줄의 파일을 읽은 다음 다중 문자 구분 기호를 사용하여 병렬화를 일치시키고 결과를 다른 변수에 저장하고 싶습니다 .
빈 줄과 후행 새 줄을 건너뛰고 후행 구분 기호가 필요하지 않습니다.
\r\n
또한, 추가 "비용"이 없다면 개행으로도 지원하지 않는 이유를 지원하고 싶습니다 \r
(물론 \n
).
스크립트는 GNU의 bash 4.2.46, sed 4.2.2, awk 4.0.2, grep 2.20, coreutils 8.22(tr, cat, Paste, sort, cut, head, tail, tee...)를 사용하여 RHEL에서 실행되어야 합니다. xargs 4.5.11 및 libc 2.17뿐만 아니라 Perl 5.16.3, Python 2.7.5 및 openjdk 11.0.8.
하루에 두 번 정도 ca 파일에서 실행되어야 합니다. 괜찮은 머신/가상 머신에 10개의 라인이 있습니다. 가독성, 유지 관리 용이성 및 단순성이 크게 저하되지 않는다면 더 높은 성능의 솔루션을 기꺼이 받아들일 것입니다.
Win7
읽을 파일은 동일한 컴퓨터나 다른 시스템에서 생성하고 수정할 수 있습니다 Win10
.
지금까지 나의 접근 방식은
joined_string_var=$(sed 's/\r/\n/g' $filepathvar | grep . | sed ':a; N; $!ba; s/\n/; /g')
그래서 먼저 모든 개행 형식을 덮어
\r
쓰고\n
출력을 grep에서 읽을 수 있도록 변경했습니다.그런 다음 빈 줄을 제거합니다.
grep .
마지막으로 sed를 사용하여 실제 라인 병합을 수행했습니다.
cat 사용을 피하기 위해 첫 번째 단계에서는 not을 사용했지만 sed
, 이것을 선호하는지 잘 모르겠습니다.tr
joined_string_var=$(cat $filepathvar | tr '\r' '\n' | grep . | sed ':a; N; $!ba; s/\n/; /g')
고쳐 쓰다:어떻게 든 간단한 리디렉션을 완전히 놓쳤습니다.
joined_string_var=$(tr '\r' '\n' <$filepathvar | grep . | sed ':a; N; $!ba; s/\n/; /g')
이 작업을 보다 우아하게 수행하는 방법에 대한 아이디어가 있습니까(명령 수가 적고 성능이 향상되며 간결성과 가독성도 떨어지지 않음)?
답변1
우아함은 올바른 정규식에서 나올 수 있습니다. 모든 줄 종결자를 원하는 구분 기호 \r
( \n
)로 변경하는 대신 (GNU sed에서는 이를 이해하는 sed 구현이 거의 없지만 모든 sed 구현이 이해하는 것은 아닙니다):s/\r/\n/g
\r\n
\r
\n
\r
-E
sed -E 's/\r\n|\r|\n/; /g'
또는 빈 줄을 제거하려면달리기이러한 줄 종결자는 다음과 같습니다.
sed -E 's/[\r\n]+/; /g'
패턴 공간에서 모든 라인 종결자를 캡처할 수 있다면 작동할 것입니다. 이는 전체 파일을 편집할 수 있도록 메모리에 저장하는 것을 의미합니다.
따라서 더 간단한 방법을 사용할 수 있습니다(GNU sed의 한 명령).
sed -zE 's/[\r\n]+/; /g; s/; $/\n/' "$filepathvar"
-z
널 바이트를 줄 종결자로 사용하여 \r
패턴 공간의 모든 합계를 효과적으로 가져옵니다.\n
모든 유형의 줄 구분 기호를 s/[\r\n]+/; /g
원하는 문자열로 변환하세요.
(마지막) 후행 구분 기호 문자를 s/; $/\n/
실제 개행 문자로 변환합니다.
노트
sed 옵션은 -z
0 구분 기호(0x00)를 사용한다는 의미입니다. 이 구분 기호는 find가 xargs( ) 옵션과 일치하는 -print0
줄 바꿈( )으로 파일 이름을 처리할 수 있어야 하기 때문에 사용됩니다 . -0
이는 일부 도구가 0으로 구분된 문자열을 처리하도록 수정되었음을 의미합니다.
이것은 개행 대신 0에서 파일을 나누는 비-posix 옵션입니다.
Posix 텍스트 파일에는 0(NIL) 바이트가 없어야 하므로 이 옵션을 사용하는 것은 처리하기 전에 전체 파일을 메모리에 캡처하는 것을 의미합니다.
NIL에서 파일을 삭제하면 sed의 패턴 공간에서 개행 문자가 편집될 수 있습니다. 파일에 NIL 바이트가 있는 경우 파일의 모든 블록에서 계속 편집할 수 있으므로 개행에 대한 아이디어는 여전히 유효합니다.
이 -z
옵션은 GNU sed에 추가되었습니다. ATT sed(posix 기반)에는 그러한 옵션이 없었고(여전히 없음) 일부 BSD sed도 여전히 없습니다.
이 옵션의 대안은 -z
전체 파일을 메모리에 캡처하는 것입니다. 이는 다음과 같은 방법으로 수행할 수 있습니다.
sed 'H;1h;$!d' # capture whole file in hold space.
sed ':a;N;$!ba' # capture whole file in pattern space.
패턴 공간에 모든 줄바꿈(마지막 줄 제외)을 배치하면 편집 가능해집니다.
sed -Ee 'H;1h;$!d;x' -e 's/(\r\n|\r|\n)/; /g
또한 오래된 sed에 대해서는 더 길고 더 명시적인 sed를 사용해야 하는데, 이는 그러한 sed가 표현식을 이해하지 못 하거나 괄호 안에 있기 때문 (\r\n|\r|\n)+
이 아닙니다 .[\r\n]+
\r
\n
[]
라인 안내
한 번에 한 줄씩 실행하는 솔루션( \r
a 는 이 솔루션에서 유효한 줄 종결자이기도 함), 이는 GNU awk를 사용하면 전체 파일을 메모리에 유지할 필요가 없음을 의미합니다(사용되는 메모리가 적음).
awk -vRS='[\r\n]+' 'NR>1{printf "; "}{printf $0}END{print ""}' file
정규식 레코드 구분 기호로 인해 GNU awk 여야 합니다 [\r\n]+
. 다른 awk에서는 레코드 구분 기호가 단일 바이트여야 합니다.
답변2
Sed를 사용하면 perl
줄바꿈을 사용하기가 더 복잡하지만 Perl은 이를 쉽게 처리할 수 있습니다.
printf 'aa\nbb\ncc\n' > file
printf 'aa2\r\nbb2\r\ncc2\r\n' > file2
printf 'aa3\rbb3\rcc3\r' > file3
따라서 줄 끝이 file
있고 거기 에 있습니다 (그런데 지금은 더 이상 사용되지 않으며 지원하는 데 별 의미가 없습니다). 이제 이를 문자열로 연결합니다.\n
file2
\r\n
file3
\r
$ joined_string_var=$(perl -pe 's/(\r\n|\r|\n)/; /g' file file2 file3)
$ echo "$joined_string_var"
aa; bb; cc; aa2; bb2; cc2; aa3; bb3; cc3;
그러나 후행 ;
구분 기호를 제거하려면 두 번째 패스가 필요합니다.
$ joined_string_var=$(perl -pe 's/(\r\n|\r|\n)/; /g' file file2 file3 | sed 's/; $//')
$ echo "$joined_string_var"
aa; bb; cc; aa2; bb2; cc2; aa3; bb3; cc3
또는 Perl에서 제거하십시오.
$ joined_string_var=$(perl -ne 's/(\r\n|\r|\n)/; /g; $k.=$_; END{$k=~s/; $//; print $k}' file file2 file3)
$ echo "$joined_string_var"
aa; bb; cc; aa2; bb2; cc2; aa3; bb3; cc3
답변3
기록을 위해 zsh
(비슷한 요구 사항이 있지만 제한 사항이 없는 경우 bash
) 다음을 수행해야 합니다.
IFS=$'\r\n'
joined=${(j[; ])$(<$filepathvar):#}
IFS=$'\r\n'
단어 분할 필드 구분 기호를 CR 또는 LF 문자로 설정합니다(ksh93 스타일$'...'
따옴표 사용).$(<file)
: 단어 분사의 영향을 받아ksh
내용처럼 확장됩니다 (후행 개행 없이).file
${list:#pattern}
일치하지 않는 목록의 요소pattern
(및ksh
s 확장자${list#pattern}
)로 확장됩니다. 여기서는 빈 줄을 제거하기 위한 패턴으로 빈 문자열이 사용됩니다.${(j[; ])list}
j
oins 목록의 요소"; "
.
답변4
f=file
python3 -c "import re
print(re.sub(r'[\r\n]+', '; ', open('$f').read().strip('\r').strip('\n')))"
perl -nF'[\r\n]+' -0777E '$,="; ";
say @F;
' file