"|" 항목을 바꾸고 싶습니다.와는 별개로파일의 각 줄에 마지막 공백을 두려면 다음을 사용하십시오.sed 전용. 나는 이런 일을 피하고 싶다:
sed -e "s/[|]/ /1" -e "s/[|]/ /1" -e "s/[|]/ /1" -e "s/[|]/ /1" -e "s/[|]/ /1" -e "s/[|]/ /1" -e "s/[|]/ /1" mydata.txt
파일 입력:
FLD1 |SFK TK |FLD2 |FLD4 |FLD5 |- |20200515 |NNNN |406 RCO 301
FLD1 |SFK TK |FLD2 |FLD4 |FLD5 |- |20200515 |NNNN |0
FLD1 |SFK TK |FLD2 |FLD4 |FLD5 |- |20200515 |NNNN |0
파일 출력:
FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |406 RCO 301
FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |0
FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |0
답변1
sed ':a;/[|].*[|]/s/[|]/ /;ta' file
/[|].*[|]/
: 라인에 파이프가 2개 있는 경우s/[|]/ /
: 첫 번째 것을 공백으로 바꿉니다.ta
: 대체된 경우 로 돌아갑니다:a
.
산출:
$ sed ':a;/[|].*[|]/s/[|]/ /;ta' file
FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |406 RCO 301
FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |0
FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |0
@steeldriver가 말했듯 이 위의 경우처럼 |
기본 정규 표현식(BRE)에서 간단히 사용할 수 없습니다 . ERE(확장 정규 표현식)를 활성화하는 플래그를 sed에 추가하는 [|]
경우 또는 를 -E
작성해야 합니다 .[|]
\|
완전성을 위해,POSIX sed 사양"제외 편집"이라고 말하세요{...},a,b,c,i,r,t,w,:,그리고#뒤에는 세미콜론이 올 수 있습니다. 그러면 위와 호환되는 대안은 다음과 같습니다.
sed -e ':a' -e '/[|].*[|]/s/[|]/ /;t a' file
답변2
와는 다른 접근 방식콰지모도의 명시적 사이클sed
:
$ sed 'h; s/.*|//; x; s/|[^|]*$//; y/|/ /; G; y/\n/|/' file
FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |406 RCO 301
FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |0
FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |0
각 행에 대해 예약된 공간에 행을 저장한 h
다음 마지막 행까지 포함하여 해당 행의 모든 항목을 삭제합니다 |
. 그런 다음 행의 원본을 바꾸고 마지막 행 |
과 그 이후의 모든 항목을 삭제합니다.
이제 패턴 공간에는 원래 줄의 첫 번째 부분이 포함되고 예약된 공간에는 줄의 마지막 부분이 포함됩니다.
첫 번째 y///
명령은 나머지 모든 항목을 |
공백으로 바꿉니다. G
사이에 개행 문자를 사용하여 패턴 공간의 끝에 예약된 공간을 추가합니다. 두 번째 y///
명령은 해당 개행 문자를 a로 변환하고 |
완료됩니다.
제한된(고정) 수의 s///
대체를 수행하고 가능한 경우 더 빠른 명령을 사용한다는 것은 이것이 내 컴퓨터에서 y///
명시적인 루프 변형(50MiB 데이터에서 ~2.3초, GNU 루프 초를 사용하는 동일한 데이터에서 ~7.8초)보다 빠르게 실행된다는 것을 의미합니다. sed
).
흥미롭게도 명시적인 루프 변경에서 역참조를 사용하면(Isaac과 내가 그랬던 것처럼) 작업 속도가 더욱 느려집니다(~33초).이삭의 변종, 내 시간은 ~29초(댓글에서), 위와 동일한 데이터 세트 및 조건에서).
awk
이것을 사용거의마지막 구분 기호를 제외한 |
모든 구분 기호를 공백으로 바꿉니다 . 그 이후로 "거의"끼워 넣다마지막 항목 앞에 공백이 있습니다 |
.
$ awk -F '|' 'BEGIN { OFS = " " } { $NF = "|" $NF; print }' file
FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |406 RCO 301
FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |0
FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |0
|
각 행을 구분된 필드 세트로 읽고 , |
마지막 필드의 시작 부분에 문자를 추가하고, 필드 구분 기호에 대한 공백이 포함된 결과 레코드를 인쇄합니다.
기본 동작을 고려하십시오 awk
(공백은 기본 출력 필드 구분 기호이고 입력 필드 구분 기호는 로 사용될 수 있음 FS
).
awk -F '|' '{ $NF = FS $NF; print }' file
또는 @Isaac의 도움으로 약간 더 짧아졌습니다.
awk -F '|' '{ $NF = FS $NF }; 1' file
답변3
Perl을 사용하면 다음과 같이 실행할 수 있습니다.
perl -pe 's/\|(?=.*\|)/ /g' ex
어디:
perl -pe
작업 - 작업 수행 및 인쇄\|(?=.*\|)
|
다른 항목을 포함하는 사용되지 않은 조회와 일치하는 정규식입니다.(?=.*|)
|
답변4
다음은 사용할 수 있는 몇 가지 대안입니다.
$ sed -e '
s/|[^|]*$/\n&/
s/\n|/\n/
y/\n|/| /
' file
$ perl -pe 's/\|/ / until tr/|/|/ == 1' file
$ perl -pe 'my $k=tr/|/|/; s/\|/ / while $k-->1' file