각 줄의 마지막 문자를 제외한 모든 문자 바꾸기

각 줄의 마지막 문자를 제외한 모든 문자 바꾸기

"|" 항목을 바꾸고 싶습니다.와는 별개로파일의 각 줄에 마지막 공백을 두려면 다음을 사용하십시오.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

관련 정보