다음과 같은 데이터가 포함된 파일이 있습니다.
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