Bash에서 "_"를 기준으로 열 분할

Bash에서 "_"를 기준으로 열 분할

안녕하세요, 저도 이와 비슷한 문제가 있습니다우편 엽서

하지만 저는 Bash를 처음 접하고 파일이 약간 다르기 때문에 답변을 수정하여 코드에 적용할 수 없습니다.

여러 열(쉼표로 구분된 모든 열)이 있는 csv 파일이 있고 분할하려는 열은 다음과 같습니다. (입력 파일)

post_id
86680728811_272953252761568
 86680728811_273859942672742
86680728811_281125741936891
86680728811_10150500662053812
_86680728811_10150500969563812
86680728811_10150501303143812
86680728811_305275689511038
_86680728811_10150501624593812
 86680728811_10150501873973812
86680728811_145945585518261

두 번째 ID 번호(밑줄 다음 번호)를 추출하고 싶습니다. 일부 열은 숫자로 시작하고, 일부는 공백으로 시작하고, 일부는 "_"로 시작한다는 점을 기억하세요.

내가 원하는 출력은 각각 "_"으로 구분된 ID를 포함하는 두 개의 새 열을 추가하는 것입니다. 첫 번째 줄의 예:

page ID             post ID 
86680728811         272953252761568

정규식을 사용하여 숫자를 읽으려고 합니다.

awk -F',' '{print $2} /(?<=_)[0-9]+/' FB_Dataset.csv

하지만 지금까지 시도한 모든 것이 작동하지 않습니다. 어떤 제안이라도 도움이 될 것입니다. 감사해요

답변1

awk -F', *_?' -v OFS=, '
  NR==1 {
    for (i=1;i<=NF;i++) {
      if ($i == "post_id") {
        $i = "page ID" OFS "post ID";
        col=$1;
      };
    };
    print;
    next
  };

  {
    split($col,a,/_/);
    $col=a[1] OFS a[2];
    print;
  };
  ' FB_Dataset.csv

표시 중인 필드 데이터가 일관되지 않은 형식(일부는 공백으로 시작하고 일부는 밑줄로 시작하고 일부는 둘 다)이므로 이 awk스크립트는 정규식 , *_?("쉼표 뒤에 0개 이상의 공백이 오고 선택적으로 뒤에 공백이 옴)을 사용합니다. 밑줄 ")을 필드 구분 기호( FS)로 사용합니다.

또한 출력 필드 구분 기호( OFS)를 쉼표로 설정합니다.

입력을 읽을 때 첫 번째 행(CSV 헤더)과 나머지 모든 행을 다르게 처리합니다.

첫 번째 줄( NR==1)에서는 각 필드의 값을 확인하여 문자열을 찾습니다 "post_id". 문자열이 발견되면 필드 값을 변경하여 두 개의 새 필드 이름( page IDpost ID)과 나중에 사용할 수 있도록 OFS필드의 인덱스 번호를 변수에 저장합니다 . col마지막으로 수정된 행을 인쇄합니다.

이는 유효한 CSV 파일에 대한 필드 이름이 고유해야 한다고 가정합니다. 여러 필드에 name 이 있으면 제대로 작동하지 않습니다 post_id.

나머지 행의 경우 $col밑줄( ) 문자를 구분 기호로 사용하여 필드를 배열로 분할합니다. 그런 다음 $col을 배열의 처음 두 요소로 바꾸고 수정된 행을 인쇄합니다.a_OFS

입력 예:

A,B,C,post_id,D,E,F
a,b,c,86680728811_272953252761568,d,e,f
a,b,c, 86680728811_273859942672742,d,e,f
a,b,c,86680728811_281125741936891,d,e,f

예제 출력:

A,B,C,page ID,post ID,D,E,F
a,b,c,86680728811,272953252761568,d,e,f
a,b,c,86680728811,273859942672742,d,e,f
a,b,c,86680728811,281125741936891,d,e,f

헤더 행에서 이 필드는 두 개의 필드( 및 ) post_id로 변환되었으며 , CSV 데이터에서는 해당 필드가 두 개의 필드로 분할되었습니다.page IDpost ID

그런데 스크립트는 post_id헤더 행에서 일치하는 필드 이름( )을 검색하기 때문에 분할하려는 필드 앞 및/또는 뒤의 필드 수에 관계없이 처리할 수 있습니다. 이 샘플 데이터를 통해 네 번째 필드에 우리가 원하는 이름이 포함되어 있음을 확인했습니다.col=4


$i및 awk $col에서는 쉘에서와 다른 의미를 갖습니다.

  • 셸에서 이는 다음 변수를 의미합니다.이름i그리고 col.
  • 에서는 awk"인덱스 번호가 변수 값과 동일한 필드의 값i(또는 변수 col)"입니다. 즉, 간접 참조를 통해 필드에 액세스합니다.

    예를 들어, if i=1then은 $i"필드 1의 값"을 의미하며 와 동일합니다 $1.

    예를 들어, 필드 번호에 대해 산술 연산을 수행해야 하는 경우 유용합니다. awk에서는 NF현재 입력 라인의 마지막 필드의 인덱스 번호를 포함하는 자동 생성 변수입니다. so 는 $NF"마지막 필드의 값"을 의미하고 $(NF-1)"마지막 필드에서 두 번째 필드의 값" 등을 의미합니다.

답변2

이것이 당신에게 효과가 있습니까? 나는 다음과 같은 형식을 가정하겠습니다.

A B C post_id
a,b,c,86680728811_272953252761568
a,b,c, 86680728811_273859942672742
a,b,c,86680728811_281125741936891
a,b,c,86680728811_10150500662053812
a,b,c,_86680728811_10150500969563812
a,b,c,86680728811_10150501303143812
a,b,c,86680728811_305275689511038
a,b,c,_86680728811_10150501624593812
a,b,c, 86680728811_10150501873973812
a,b,c,86680728811_145945585518261

그런 다음 명령

cat file | sed -Ee 's/(.*)post_id/\1page ID post I/' -e 's/,[_ ]/,/' -e 's/_/,/'

산출:

A B C page ID post ID
a,b,c,86680728811,272953252761568
a,b,c,86680728811,273859942672742
a,b,c,86680728811,281125741936891
a,b,c,86680728811,10150500662053812
a,b,c,86680728811,10150500969563812
a,b,c,86680728811,10150501303143812
a,b,c,86680728811,305275689511038
a,b,c,86680728811,10150501624593812
a,b,c,86680728811,10150501873973812
a,b,c,86680728811,145945585518261

-E확장 정규식(GNU)을 사용하면 그룹을 캡처할 수 있습니다.


헤더를 변경하여 page ID post ID캡처 첫 번째 그룹 (.*)까지 추가 post_id하고 캡처된 그룹으로 교체합니다 \1.page ID post ID

's/(.*)post_id/\1page ID post ID/'

_쉼표 뒤의 줄에서 선행 공백과 밑줄을 제거하고 단일 쉼표로 바꿉니다.

sed 's/,[_ ]/,/'

마지막으로 밑줄을 _쉼표로 바꿉니다.

sed 's/_/,/'

불필요한 명령을 제거했습니다. cut(이것은 내가 시도한 다른 명령을 상기시켜줍니다.)

답변3

나는 다음을 사용할 것이다:

awk -F' *_?' '{ print $(NF-1), $NF }' infile

관련 정보