줄 분할 및 누락된 필드 바꾸기

줄 분할 및 누락된 필드 바꾸기

다음 줄을 "분할"하는 방법을 아는 사람이 있습니까? (이것은 단지 예일 뿐입니다.)

mercedes|$40000|black|$42000|white|$41000|red
audi|$31000|blue|$10000|white
mercedes|$5000|blue

내 예상 결과는 다음과 같습니다

mercedes|$40000|black
mercedes|$42000|white
mercedes|$41000|red
audi|$31000|blue
audi|$10000|white
mercedes|$5000|blue

감사해요

답변1

awk두 번째 필드로 시작하는 각 줄의 필드 쌍을 출력하고 각 출력 쌍 앞에 해당 줄의 첫 번째 필드를 추가하는 간단한 스크립트입니다.

$ awk -F '|' 'BEGIN { OFS=FS } { for (i = 2; i+1 <= NF; i += 2) print $1, $i, $(i+1) }' file
mercedes|$40000|black
mercedes|$42000|white
mercedes|$41000|red
audi|$31000|blue
audi|$10000|white
mercedes|$5000|blue

이는 입력이 예상한 대로라고 가정합니다. 즉, 최종 데이터는 세 개의 열로 구성되어야 합니다. 이는 입력이 엄격하게 준수되어야 함을 의미합니다.

title|pair 1a|pair 1b|pair 2a|pair 2b|...|pair Na|pair Nb

답변2

awk -F'[|]' '{ for(i=3; i<NF; i+=2) sub($i, $i ORS $1) }1' infile

첫 번째 매개변수에 유의하세요.sub(regexp, replacement [, target])기능~이다정규식그래서 그것은 $i다음과 같이 취급 됩니다정규식.

자세히 알아보기sub(), gsub() 및 gensub() 함수의 '\' 및 '&'이 함수의 두 번째 매개변수에 대해서도 마찬가지입니다.


또는 위에서 언급한 sub() 문제 없이 다음과 같이 수행하십시오.

awk 'BEGIN{ FS=OFS="|" } { for(i=3; i<NF; i+=2) $i= $i ORS $1 }1' infile 

답변3

python처음 두 필드를 채우려면 모듈 에 itertools첫 번째 필드를 반복적으로 제공하십시오 .

python3 -c 'import sys
import itertools as it
ifile = sys.argv[1]
ofs = fs = "|"
with open(ifile) as f:
  for l in f:
    L = l.rstrip("\n").split(fs)
    for a,b in zip(it.repeat(L.pop(0)),zip(*[iter(L)]*2)):
      print(a,*b,sep=ofs)
' file

perl또한 첫 번째 필드뿐만 아니라 선행 2+3 필드를 인쇄한 다음 두 번째 및 세 번째 필드를 삭제하여 다음 필드가 대신되도록 하는 경우에도 작동합니다.

perl -F'[|]' -lane '$,="|";
  print $F[0], splice(@F,1,2)
    while @F > 3;
  print @F;
' file

GNU sed확장 정규식 모드를 활성화합니다 -E.

  • 세 번째 필드의 끝에 표시하면 필드 1에서 필드 3까지 인쇄할 준비가 됩니다.
  • 다음 인쇄 라운드를 준비하기 위해 세 번째 필드 다음에 첫 번째 필드를 복사합니다.
sed -Ee '
  s/[|]/\n/3;P
  s/^([^|]+[|]).*\n/&\1/;D
' file

설명하다:

  • 다음과 같은 줄을 상상해 보세요.
    • 자동차 브랜드 | p1 | c2 |
  • 우리는 브랜드가 별도의 줄에 있는 가격/색상 튜플과 쌍을 이루기를 원합니다.
  • 세 번째 파이프 구분 기호를 개행 문자로 바꿉니다.s/[|]/\n/3
  • 이제 패턴 공간을 시각화합니다.
    • 자동차 브랜드 | c1 \n p2 | c1 \n p2 |
  • sed 명령 P(대문자 pee)은 첫 번째 개행 문자까지 표준 출력으로 인쇄합니다.
  • 이 단계의 출력은 다음과 같습니다.
    • 자동차 브랜드 |
  • 이것이 첫 번째 가격/색상 쌍입니다. 지금 해야 할 일은 자동차 브랜드를 다음 가격/색상 쌍으로 복사하는 것입니다.
    • s/^([^|]+[|]).*\n/&\1/
    • 대괄호는 일치된 항목, 즉 첫 번째 파이프 구분 기호를 포함한 선행 데이터를 기억합니다. 개행 문자까지 일치합니다. 교체 부품은 우리 기억에 있는 (자동차 브랜드|)와 일치하는 부품 (&)입니다.
    • 이제 패턴 공간은 Car_brand | c1 \n 자동차 브랜드 | c2 |
  • 이것elete 명령은 첫 번째 개행 문자가 나올 때까지 계속됩니다.
    • 이제 패턴 공간은 Car _brand | c2 |
  • 이 명령의 속성은 D첫 번째 개행 문자까지 제거하고 나머지를 제공한 후 나머지 패턴 공간에 sed 코드를 다시 적용한다는 것입니다.
  • 간단히 말해서 이는 반복 작업에 해당합니다.

결과:

mercedes|$40000|black
mercedes|$42000|white
mercedes|$41000|red
audi|$31000|blue
audi|$10000|white
mercedes|$5000|blue

답변4

그리고 perl:

perl -F"\|" -le '$,="|";
for (my $a=1;$a<@F;$a+=2) 
{print $F[0],$F[$a], $F[$a+1]}' input
  • -F"\|"입력 필드 구분 기호는 다음과 같이 설정됩니다.|
  • $,="|";출력 필드 구분 기호는 다음과 같이 설정됩니다.|
  • $a<scalar @F;Perl의 필드는 0부터 시작하므로 이는 scalar @F총 필드 수를 알려줍니다 .$a<scalar @F

이것은답변@Kusalananda 작성 그러나 perl.

관련 정보