내 데이터가 여러 행에 있고 이를 탭으로 구분된 여러 열로 바꾸고 싶습니다.
ABC 0.98 0.58 5.87 0.01
DEF 0.88 5.85 6.89 0.25
GHI 8.99 5.66 4.78 6.22
입력하다
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
위 형식으로 출력을 얻을 수 있도록 이 문제를 해결하도록 도와주실 수 있나요?
답변1
GNU 사용 datamash
:
$ datamash -W transpose <file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
datamash
이는 공백으로 구분된 행을 탭으로 구분된 열로 바꾸는 데 사용됩니다 .
이 옵션을 사용하여 다른 출력 구분 기호를 설정할 수 있습니다 --output-delimiter
. 여기서는 예상되는 출력을 재현하는 것처럼 보이는 공백을 사용했습니다.
$ datamash -W --output-delimiter=' ' transpose <file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
답변2
모든 Unix 시스템의 모든 쉘에서 awk를 사용하십시오.
$ cat tst.awk
{
for ( rowNr=1; rowNr<=NF; rowNr++ ) {
vals[rowNr,NR] = $rowNr
}
}
END {
for ( rowNr=1; rowNr<=NF; rowNr++ ) {
for ( colNr=1; colNr<=NR; colNr++ ) {
printf "%s%s", vals[rowNr,colNr], (colNr<NR ? OFS : ORS)
}
}
}
$ awk -f tst.awk file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
다음 명령을 사용하면 위의 작업을 더 간단하게 수행할 수 있습니다.
$ cat tst.awk
{
for ( rowNr=1; rowNr<=NF; rowNr++ ) {
vals[rowNr] = (rowNr in vals ? vals[rowNr] OFS : "") $rowNr
}
}
END {
for ( rowNr=1; rowNr<=NF; rowNr++ ) {
print vals[rowNr]
}
}
$ awk -f tst.awk file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
하지만 이 경우 동일한 변수에 새 값을 지속적으로 재할당한다는 점에 유의하세요. vals[rowNr]
이는 awk가 필요한 것이 무엇인지 결정해야 하기 때문에 각 새 변수에 대해 한 번 할당하는 것에 비해 awk의 작업이 상대적으로 느립니다. 얼마나 많은 메모리가 필요합니까? 새 값을 저장하려면 이전 값을 새 메모리 위치로 이동하고 새 값을 추가한 다음 이전 위치를 해제하세요. 그러면 많은 작은 청크 대신 몇 개의 큰 메모리 청크가 필요하므로 awk가 찾기가 더 어렵습니다. 변수가 크기에 따라 증가하므로 메모리를 확보합니다. 또한 출력 형식과 입력 읽기를 혼합하므로 생성된 코드는 첫 번째 스크립트보다 더 긴밀하게 결합됩니다. 그러나 그것은 끔찍하지 않습니다. 적어도 코드는 간단합니다.
답변3
BSD 작업처럼 들립니다 rs
(1983년 이후 BSD에 포함되었지만 일반적으로 다른 시스템에는 기본적으로 설치되지 않음).
$ cat file
ABC 0.98 0.58 5.87 0.01
DEF 0.88 5.85 6.89 0.25
GHI 8.99 5.66 4.78 6.22
$ rs -T < file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
답변4
사용행복하다(이전 Perl_6)
raku -e '.put for [Z] lines.map(*.words);'
또는 (2단계):
raku -e 'my @a = lines.map(*.words); .put for [Z] @a;'
입력 예:
ABC 0.98 0.58 5.87 0.01
DEF 0.88 5.85 6.89 0.25
GHI 8.99 5.66 4.78 6.22
예제 출력:
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
두 번째 예를 간략하게 설명하기 위해 배열을 lines
읽고 @a
각 배열을 공백으로 구분된 words
(예: 열)로 나눕니다. 두 번째 문에서는 데이터가 out put
이지만 [Z]
zip과 같은 축소 연산자를 사용하여 첫 번째 배열 요소의 첫 번째 단어를 가져와서 두 번째 배열 요소의 첫 번째 단어와 세 번째 배열 요소의 첫 번째 단어를 반환합니다. 함께 등등
또는 CSV/TSV 요구 사항이 더 엄격한 경우 Text::CSV
명령줄에서 Raku 모듈을 사용할 수 있습니다.
~$ raku -MText::CSV -e '.put for [Z] csv(in => $*IN, sep => " ");' < file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
https://docs.raku.org/언어/operators#index-entry-[]_(reduction_metaoperators)
https://unix.stackexchange.com/a/670344/227738
https://raku.org