구분 기호를 사용하여 행을 추출하고 파일의 열로 추가합니다.

구분 기호를 사용하여 행을 추출하고 파일의 열로 추가합니다.

다음과 같은 데이터가 포함된 파일이 있습니다.

a 1
b 2
c,d,e 3,4,5
f 6
g,h 7,8 

...다음과 같은 출력이 필요합니다.

a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8

Python을 사용하여 이 작업을 수행할 수 있지만 쉘 스크립트를 사용하여 이 작업을 시도하고 싶습니다. 먼저 구분 기호 ","가 포함된 줄을 분리한 다음 작업을 계속할 생각입니다. 지금까지 나는 이것을 행을 분리하는 데 사용했습니다.

perl -F, -ane 'print if $#F >=1' filename

...하지만 다음 단계에서 막히네요.

답변1

그리고perl

$ perl -lane '@v=split/,/,$F[1]; $i=0;
              print "$_ $v[$i++]" for split/,/,$F[0]' ip.txt
a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8

첫 번째/두 번째 열을 분할하고 인덱스 카운터를 초기화한 다음 다른 열을 반복적으로 분할하여 쌍을 인쇄합니다.

-a옵션은 자동으로 입력 줄을 공백으로 분할하고 결과를 @F배열에 저장합니다.

답변2

Awk해결 방법(첫 번째 필드에 포함된 "키" 수는 $1항상 두 번째 필드에 포함된 "값" 수와 일치한다고 가정 $2):

awk '$1 ~ /,/{
         len = split($1, keys, ",");
         split($2, vals, ",");
         for (i = 1; i <= len; i++) print keys[i], vals[i];
         next
    }1' file

산출:

a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8

답변3

sed 편집기를 사용하여 이를 수행하는 한 가지 방법은 다음과 같습니다.

sed -e '
   s/,/\n/
   s/\(\n.*[[:blank:]]\)\([^,]*\),/ \2\1/
   P;D
' input.file

피복재:

  • 두 번째 필드에서 쉼표로 구분된 선행 요소를 자릅니다.
  • 그런 다음 이 요소는 첫 번째 필드의 쉼표로 구분된 선행 요소에 추가됩니다.
  • 첫 번째 필드의 선행 요소를 인쇄한 다음 제거합니다.
  • 패턴 공간의 나머지 부분이 빌 때까지 이 과정을 반복합니다.

Perl을 사용하는 또 다른 방법은 다음과 같습니다.

perl -lane '
   my($kref, $vref, %h) = map { [split /,/] } @F[0,1];
   @h{@$kref} = @$vref;
   print "$_  $h{$_}" for @$kref;
' input.file

또 다른 방법은 다음과 같습니다.

perl -lpe 'print "$1 $3" while s/^([^,]*),(.*\h)([^,]*),/$2/' input.file

피복재:

  • 다음과 같은 정규식을 살펴보십시오. (Perl은 파일에서 한 번에 한 줄씩 읽습니다.) 그런 다음:
    • ^([^,]*)현재 행의 첫 번째 필드에 있는 쉼표로 구분된 선행 요소를 선택해야 합니다. 이는 $1 변수에 저장됩니다.
    • (.*\시간)while 루프의 다음 반복에서는 첫 번째 필드의 두 번째 쉼표로 구분된 요소부터 시작하여 두 번째 필드의 두 번째 쉼표로 구분된 요소의 시작 부분까지의 내용이 유지되어야 합니다. 이는 $2 변수에 저장됩니다.
    • ([^,]*)쉼표로 구분된 선행 요소는 현재 행의 두 번째 필드에서 선택해야 합니다. 이는 $3 변수에 저장됩니다.
    • 이제 "$1 $3"이 STDOUT에 인쇄되고 해당 줄은 $2로 줄어듭니다. 이제 while 루프는 이 편집된 라인에서 이전 라인의 $2만큼 작업을 다시 수행합니다. ..... 이는 s///가 성공할 때까지 반복됩니다. 쉼표가 부족하면 실패합니다. 이 시점에서 "c 5" 줄의 나머지 부분은 -p 모드에서 Perl의 기본 동작을 통해 STDOUT에 인쇄됩니다.
  • 첫 번째 및 두 번째 필드에서 쉼표로 구분된 선행 요소를 가져옵니다.
  • 이러한 요소를 인쇄하고 삭제하여 현재 레코드를 축소합니다.
  • 현재 레코드에 쉼표가 2개 있으면 레코드를 반복합니다.
  • 마지막 쌍은 Perl의 -p 옵션으로 인해 자동으로 인쇄됩니다.

perl -lane '
   my($kref, $vref) = map { [split /,/] } @F;
   print shift @$kref, " ", shift @$vref while @$kref && @$vref;
' input.file

피복재:

  • 키는 @$kref 배열에 저장되고 해당 값은 @$vref에 저장됩니다. 여기에는 해시가 관련되어 있지 않습니다.
  • 또한 배열의 상단을 인쇄한 다음 상단을 삭제하고 플러시하고 두 배열이 모두 비어 있지 않으면 반복합니다.

산출:

a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8

답변4

"쉘 스크립트 사용" - 이것은 bash입니다:

while read -r key value; do
    IFS=, read -ra keys <<<"$key"
    IFS=, read -ra vals <<<"$value"
    for ((i=0; i < ${#keys[@]}; i++)); do
        echo "${keys[i]} ${vals[i]}"
    done
done <<END
a 1
b 2
c,d,e 3,4,5
f 6
g,h 7,8 
END

관련 정보