답변1
출력에 hd
FS 문자(16진수)를 표시하는 데 사용됩니다.1c
$ perl -0777 -pe 's/^(\d{3}.*)\n/$1/mg' input.txt | hd
00000000 30 30 31 1c 42 61 6b 65 72 20 53 74 2e 4c 6f 6e |001.Baker St.Lon|
00000010 64 6f 6e 1c 33 1c 34 1c 37 0a 30 30 32 1c 50 65 |don.3.4.7.002.Pe|
00000020 6e 6e 79 20 4c 61 6e 65 4c 69 76 65 72 70 6f 6f |nny LaneLiverpoo|
00000030 6c 1c 38 38 1c 35 1c 37 0a |l.88.5.7.|
00000039
그렇지 않은 경우 hd
출력은 다음과 같습니다(FS 문자는 보이지 않지만 여전히 존재하므로~ 할 것이다-i
다른 파일로 리디렉션되거나 "위치에서 편집" 옵션이 사용된 경우 출력에 있는 경우):
$ perl -0777 -pe 's/^(\d{3}.*)\n/$1/mg' input.txt
001Baker St.London347
002Penny LaneLiverpool8857
두 경우 모두 이 Perl 스크립트는 전체 파일을 한 번에 읽고( -0777
) 각 "줄"(3자리 숫자로 시작하여 다음 개행 문자를 포함하지 않는 일련의 문자)을 캡처한 다음 캡처된 텍스트로 바꿉니다. (개행 없음). 즉, 세 자리 숫자로 시작하는 "줄"에서 개행 문자를 제거합니다.
$1
원하지 않는 개행 문자를 직접 제거하는 대신 공백으로 바꾸려면 RHS 뒤에 공백을 추가하세요. 또는 \x1c
개행 문자를 FS 문자로 변경하려는 경우.
검색 s///
및 바꾸기 작업에서는 m
("여러 줄 문자열") 및 g
("전역") 정규식 수정자를 사용합니다. g
정규식(sed 포함)을 사용하고 정규식이 "전역" 반복 일치를 수행하도록 하는 여러 도구에 공통적이지만 m
Perl에만 해당됩니다.
출처 man perlre
("수정자" 섹션 검색):
m
일치하는 문자열을 여러 줄로 처리합니다. 즉, 문자열의 첫 번째 줄의 시작과 마지막 줄의 끝을 일치시키는 것에서 문자열의 모든 줄의 시작과 끝을 일치시키는^
것으로 변경합니다.$
참고 1: 이 스크립트는 "필드" 구분 기호가 무엇인지 상관하지 않습니다. 필드를 전혀 찾거나 사용하지 않습니다. 필드 구분 기호가 공백, 탭, 콜론 또는 기타 항목(물론 개행 문자 제외)인 경우에도 작동합니다.
참고 2: 원치 않는 개행 문자 다음에 오는 필드가 세 자리 숫자로 시작하는 경우 이 방법은 작동하지 않습니다 123 London
. 이 문제를 처리하려면 입력 필드를 구문 분석하고 계산할 수 있는 더 복잡한 스크립트가 필요합니다.
답변2
당신은 그것을 사용할 수 있습니다 awk
:
awk '{
while (NF < 5 && getline cmp) { $0=$0"<br>"cmp }
if (NF > 5) {
print "#ERROR"
count++
}
print
}
END{
if (count) {
print "FAILED "count" lines" > "/dev/stderr"
exit 8
}
}' FS=$'\x1c'
awk
지정된 구분 기호가 있는 필드 구문 분석에 매우 적합NF
현재 행의 필드 수를 알려줍니다.- 줄 바꿈이 항상 두 번째 필드에 있도록 하고 언제 줄을 완성해야 하는지 알 수 있습니다. 다음 줄을 읽고 붙여넣기만 하면 됩니다. 공백으로 표시하는 것
<br>
보다 낫습니다 . 정보를 잃습니다. - 줄의 마지막 필드에 개행 문자가 나타날 수 있으면 더 어려워지지만 어쨌든 이 스크립트는 오류를 포착하는 것이 안전합니다.
아스타?
답변3
사용행복하다(이전 Perl_6)
raku -e 'slurp.split("\x1C").join("\t").put;'
입력 예(탭으로 구분):
~$ cat FS_test.txt
001 Baker St.
London 3 4 7
002 Penny Lane
Liverpool 88 5 7
~$ cat FS_test.txt | xxd
00000000: 3030 3109 4261 6b65 7220 5374 2e0a 4c6f 001.Baker St..Lo
00000010: 6e64 6f6e 0933 0934 0937 0a30 3032 0950 ndon.3.4.7.002.P
00000020: 656e 6e79 204c 616e 650a 4c69 7665 7270 enny Lane.Liverp
00000030: 6f6f 6c09 3838 0935 0937 0a ool.88.5.7.
탭 문자를 다음으로 변환합니다 FS
(MacOS의 View Hex 사용 xxd
).
~$ raku -e 'slurp.split("\t").join("\x1C").put;' baker_st_FS_test.txt | xxd
00000000: 3030 311c 4261 6b65 7220 5374 2e0a 4c6f 001.Baker St..Lo
00000010: 6e64 6f6e 1c33 1c34 1c37 0a30 3032 1c50 ndon.3.4.7.002.P
00000020: 656e 6e79 204c 616e 650a 4c69 7665 7270 enny Lane.Liverp
00000030: 6f6f 6c1c 3838 1c35 1c37 0a0a ool.88.5.7..
탭을 -로 변환하고 FS
다시 되돌립니다( FS
-to-tabs):
~$ cat FS_test.txt | raku -e 'slurp.split("\t").join("\x1C").put;' | raku -e 'slurp.split("\x1C").join("\t").put;'
001 Baker St.
London 3 4 7
002 Penny Lane
Liverpool 88 5 7
~$ cat FS_test.txt | raku -e 'slurp.split("\t").join("\x1C").put;' | raku -e 'slurp.split("\x1C").join("\t").put;' | xxd
00000000: 3030 3109 4261 6b65 7220 5374 2e0a 4c6f 001.Baker St..Lo
00000010: 6e64 6f6e 0933 0934 0937 0a30 3032 0950 ndon.3.4.7.002.P
00000020: 656e 6e79 204c 616e 650a 4c69 7665 7270 enny Lane.Liverp
00000030: 6f6f 6c09 3838 0935 0937 0a0a 0a ool.88.5.7...
각 분할/병합 왕복은 파일 끝에 빈 줄을 추가합니다. .subst(/\n/, :nth(*))
Final 앞에 루틴 호출을 삽입 하여 이러한 문제를 제거하십시오 .put
. 또는 .trim-trailing
슬러핑된 파일을 실행하여 후행 공백을 모두 제거하세요. (또한 hex 뷰어 아이디어를 제공한 @cas에게 감사드립니다).
부록: Raku의 trans
포스트 루틴도 작동합니다:
raku -e 'slurp.trans("\x1C" => "\t").put;'