다음 데이터 세트가 있습니다.
M1 1 1233
M2 1 3212
M3 1 55323
M4 1 4444233
M5 1 23444
M6 1 555333
M7 1 55567
M8 2 22224
M9 2 55566
M10 2 4567
M11 3 44242
M12 3 234234
M13 4 2233
M14 4 2442
M15 4 322352
M16 4 235242
M17 4 2324524
M18 5 232342
M19 6 2322523
M20 6 2332523
두 번째 열의 값을 기반으로 배열을 만들고 싶습니다. 1
두 번째 열의 모든 행에 다른 명령을 적용하고, 두 2
번째 열의 행에 다른 명령을 적용하고, 다른 파일에 저장하고 싶은데 어떻게 해야 할지 모르겠습니다. while
명령을 사용해 보았지만 모든 시도가 실패했습니다.
이 코드의 출력은 배열의 각 인덱스에 있는 원본 파일의 하위 집합이어야 합니다. 예를 들면 다음과 같습니다.
인덱스1
M1 1 1233
M2 1 3212
M3 1 55323
M4 1 4444233
M5 1 23444
M6 1 555333
M7 1 55567
indexi2
M8 2 22224
M9 2 55566
M10 2 4567
등등
인덱스 i6
M19 6 2322523
M20 6 2332523
이 인덱스에 다른 명령을 적용하고 싶습니다.
쉘 스크립트 및/또는 awk에서 이 작업을 어떻게 수행합니까?
답변1
awk에서 최상의 결과를 얻을 수 있습니다.
awk '{ print > "index i"$2 }' < input
셸에서만 이 작업을 수행할 수도 있습니다.
while read a b c
do
printf '%s\n' "$a $b $c" >> "index i$b"
done < input
awk 솔루션에는 다음과 같은 장점이 있습니다.
- 기존 파일을 덮어쓰게 됩니다. 쉘 스크립트는 기존 파일에 추가됩니다. (이것이 당신이 원하는 것일 수도 있다고 생각합니다. 그럴 경우 awk 스크립트
>>
대신 를 사용하여 수행할 수 있습니다 .)>
- awk 스크립트는 입력 파일 간격을 유지합니다. 쉘 스크립트는 여러 공백을 단일 공백으로 줄입니다.
- 대용량 데이터 파일의 경우 awk 스크립트가 약간 더 빠를 수 있습니다.
답변2
G-Man의 답변에 추가 :예, sh만 사용하면 똑같은 결과를 얻을 수 있습니다.(이것은 중복 질문의 사양이므로거기, G-Man이 답변하기 9시간 전에 답변했습니다.)
등에 값을 할당 set
할 수 있는 기능이 내장되어 있습니다 . 다음은 bash 매뉴얼 페이지의 인용문입니다(sh에도 적용됩니다).$1
$2
$3
설정[{-options|+options|--}] 인수...
set 명령의 세 번째 용도는 쉘의 위치 매개변수 값을 지정된 args로 설정하는 것입니다. 옵션을 변경하지 않고 위치 매개변수를 변경하려면 설정할 첫 번째 매개변수로 "--"를 사용하십시오. args가 없으면 set 명령은 모든 위치 인수를 지웁니다("shift $#" 실행과 동일).
그래서 우리는 이렇게 할 수 있습니다:
set -f
while read ln; do
set -- $ln
printf '%s\n' "$ln" >> "index i"$2
done < input
set +f
에서는 필드로 나누어 set -- $ln
지며 $ln
, n번째 필드는 n번째 위치 매개변수에 할당됩니다.
다음 줄의 따옴표는 $ln
내용의 무결성(간격 유지 등)을 보장합니다.
* 및 ?와 같은 와일드카드 문자를 방지 set -f
합니다 . set +f
파일이 복잡해지지 않도록 하세요 set
. 이 질문을 제기한 Scott에게 감사드립니다.
대신 printf
원래는 을 사용했는데 echo
Scott의 두 번째 댓글( echo
상대방이 로 줄을 바꾸면 혼란스러울 수 있음) 덕분에 이를 대신 사용하곤 했습니다.-n
-e
echo
printf
이는 sh가 이러한 유형의 작업에 적합하지 않을 수 있음을 시사합니다. 최소한 정규식을 지원하는 bash를 사용하십시오. 하지만 노력하면 가능합니다.
awk의 경우 "약간 빠르다"는 것이 아니라 디스크 IO를 고려하지 않으면 훨씬 더 빠릅니다. 따라서 먼저 awk를 사용하십시오.
그건 그렇고, "두 개의 답이 하나가 너무 많으면 두 개의 질문이 둘이 너무 많다"는 말을 들어 본 적이 없을 것입니다.
내가 방금 말했으니까 ;)
하지만 다음번에는 선택을 하고 계속해서 집중할 수 있도록 하세요.
답변3
주문하다
for i in `awk '{if(!seen[$2]++)print $2}' y.txt`;do awk -v i="$i" 'BEGIN {print "index i"i}$2==i {print $0}END {print "========================================"}' y.txt; done
산출
index i1
M1 1 1233
M2 1 3212
M3 1 55323
M4 1 4444233
M5 1 23444
M6 1 555333
M7 1 55567
========================================
index i2
M8 2 22224
M9 2 55566
M10 2 4567
========================================
index i3
M11 3 44242
M12 3 234234
========================================
index i4
M13 4 2233
M14 4 2442
M15 4 322352
M16 4 235242
M17 4 2324524
========================================
index i5
M18 5 232342
========================================
index i6
M19 6 2322523
M20 6 2332523
========================================