내가 얻는 여러 줄 출력은 다음과 같습니다.
실제 출력:
GenuineIntel,Intel(R) Xeon(R) CPU E5-2687W 0 @ 3.10GHz,CPU0,64,EM64T Family 6 Model 45 Stepping 7,(null),3093,0
GenuineIntel,Intel(R) Xeon(R) CPU E5-2687W 0 @ 3.10GHz,CPU1,64,EM64T Family 6 Model 45 Stepping 7,(null),3093,0
#
Bash 스크립트에서는 위 출력을 기호로 구분된 한 열과 쉼표로 구분된 두 열의 값이 있는 행으로 변환해야 합니다 .
예상 출력:
GenuineIntel#GenuineIntel,Intel(R) Xeon(R) CPU E5-2687W 0 @ 3.10GHz#Intel(R) Xeon(R) CPU E5-2687W 0 @ 3.10GHz,CPU0#CPU1 and so on.
어떻게 하나요?
답변1
awk
다음은 파일의 특정 내용에 의존하지 않는 보다 일반적인 접근 방식입니다 .
awk -F, '{for(i=1;i<=NF;i++){a[NR][i]=$(i)}}
END{
for(i=1;i<NF;i++){printf "%s#%s,",a[1][i],a[2][i]}
print a[1][NF]"#"a[2][NF]
}' file
설명하다
for(i=1;i<=NF;i++){a[NR][i]=$(i)}
: 각 행의 필드( 로 구분됨-F,
)를 반복하여 변수를i
1부터 필드 수( )까지의NF
모든 값 으로 설정합니다.NR
현재 줄 번호입니다. 귀하의 예에서는 1 또는 2입니다.a[NR][i]=$(i)
행당 하나씩 2D 배열을 설정하고 여기에 각 필드를 저장합니다. 기본적으로 배열은a
다음과 같습니다.1 2 3 1 1st field of 1st line 2nd field of 1st line 3rd field of 1st line 2 1st field of 2nd line 2nd field of 2nd line 3rd field of 2nd line
등. 그러면 이것이
a[1][2]
첫 번째 행의 두 번째 필드가 됩니다.END{}
: 파일의 나머지 부분을 처리한 후 이 작업을 실행합니다.for(i=1;i<NF;i++){printf "%s#%s,",a[1][i],a[2][i]}
: 모든 필드를 반복하고 첫 번째 행의 현재 필드#
와 두 번째 행의 해당 필드를 인쇄합니다.print a[1][NF]"#"a[2][NF]
:마지막 필드를 인쇄합니다(한 줄씩). 이것은 별도로 수행되므로 다른 것을 인쇄하고 그 뒤에 쉼표를 붙일 수 있지만 이 것 뒤에는 개행 문자가 옵니다.
Perl에서도 동일한 아이디어가 작동합니다.
perl -F, -ane 'chomp($F[$#F]);
$k{$.}=\@F;
END{
for($l=0;$l<$#F;$l++){
print "${$k{1}}[$l]#${$k{2}}[$l],"
}
print "${$k{1}}[$#F]#${$k{2}}[$#F]\n"}' file
이는 파일에 있는 특정 텍스트에 의존하지 않는다는 장점이 있습니다. 각 행에 동일한 수의 쉼표로 구분된 필드가 있는 한 모든 데이터 행에 대해 작동합니다.
답변2
perl
골프:
perl -F, -lane'push@{$f[$_]},$F[$_]for 0..$#F}{$,=",";$"="#";print map"@{$_}",@f'
답변3
입력 데이터가 다음 이름의 파일에 있는 경우 input
:
$ awk -F, '/CPU0/{for (i=1; i<=NF;i++) {a[i]=$i};next} {for(i=1;i<=NF-1;i++){printf a[i]"#"$i","}; print a[NF]"#"$NF}' input
GenuineIntel#GenuineIntel,Intel(R) Xeon(R) CPU E5-2687W 0 @ 3.10GHz#Intel(R) Xeon(R) CPU E5-2687W 0 @ 3.10GHz,CPU0#CPU1,64#64,EM64T Family 6 Model 45 Stepping 7#EM64T Family 6 Model 45 Stepping 7,(null)#(null),3093#3093,0#0
awk
한 번에 하나의 명령을 실행합니다.
-F,
이는
awk
입력 필드 구분 기호로 쉼표를 사용하라는 의미입니다./CPU0/{for (i=1; i<=NF;i++) {a[i]=$i};next}
첫 번째
/CPU0/
는 첫 번째 행(CPU0에 대한 행)을 선택하는 주소 선택기입니다. 이 행의 경우 모든 필드 값을 배열에 저장합니다a
. 이 명령은 다음 줄로 점프하라고next
알려줍니다 .awk
for(i=1;i<=NF-1;i++){printf a[i]"#"$i","}
이는 첫 번째 행의 열, 해시 기호, 두 번째 행의 열, 쉼표를 차례로
awk
인쇄하라는 의미입니다. 모든 필드에 대해 이 작업을 수행하고 마지막 필드를 저장합니다.i
i
printf
사용되므로 개행 문자는 인쇄되지 않습니다 .print a[NF]"#"$NF}
이는
awk
첫 번째 줄의 마지막 필드를 인쇄하고 그 뒤에 파운드 표시를 지정한 다음 두 번째 줄의 마지막 필드를 인쇄하도록 지시합니다.사용되기 때문에
print
마지막 문자는 개행 문자로 인쇄되어 출력이 완료됩니다.
답변4
$ cat /tmp/tmp
GenuineIntel,Intel(R) Xeon(R) CPU E5-2687W 0 @ 3.10GHz,CPU0,64,EM64T Family 6 Model 45 Stepping 7,(null),3093,0
GenuineIntel,Intel(R) Xeon(R) CPU E5-2687W 0 @ 3.10GHz,CPU1,64,EM64T Family 6 Model 45 Stepping 7,(null),3093,0
GenuineIntel,Intel(R) Xeon(R) CPU E5-2687W 0 @ 3.10GHz,CPU2,64,EM64T Family 6 Model 45 Stepping 7,(null),3093,0
$ awk -F ',' 'BEGIN{ORS=" ";cpu=",";print "GenuineIntel,"} {gsub(/GenuineIntel/,"");for (i=1;i<=2;i++) {printf $i};print "#";cpu=cpu"#"$3 } END{sub(/,#/,",",cpu);print cpu}' /tmp/tmp
GenuineIntel, Intel(R) Xeon(R) CPU E5-2687W 0 @ 3.10GHz # Intel(R) Xeon(R) CPU E5-2687W 0 @ 3.10GHz # Intel(R) Xeon(R) CPU E5-2687W 0 @ 3.10GHz # ,CPU0#CPU1#CPU2
완벽하지는 않습니다. #
끝에 한 줄이 더 있습니다. 앞쪽에 있으므로 ,CPU0#CPU1#CPU2
삭제할 수 있습니다.