다음과 같은 파일이 있습니다.
1
4 5 6 7 19
20
22
24 26 27
29
30
31
32
34
40
50
56
58
100
234 235 270 500
1234 1235 1236 1237
2300
2303
2304
2307
2309
일부 행에는 2개 이상의 열이 있는 반면 다른 행에는 단 하나의 열만 있는 것이 분명합니다. 결합된 각 행에 최대 4개의 열이 있도록 단일 열 행을 결합하고 싶습니다. 따라서 출력은 다음과 같아야 합니다.
1
4 5 6 7 19
20 22
24 26 27
29 30 31 32
34 40 50 56
58 100
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307
2309
실제 데이터가 크다는 점을 고려하여 이를 수행하는 방법에 대한 제안 사항이 있습니까?
답변1
약간 관용적이지만 gnu awk와 함께 작동합니다.
awk '{printf "%s",(NF==1?$0 FS:(c==0?"":RS) $0 RS)} \
{(NF==1?++c:c=0)} \
c==4{printf "\n";c=0} \
END{printf "\n"}' file
#Output
1
4 5 6 7 19
20 22
24 26 27
29 30 31 32
34 40 50 56
58 100
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307
2309
설명하다:
awk 변수:
NF=필드 수
FS=필드 구분 기호=기본 공백
RS=레코드 구분 기호=기본 줄 바꿈.
c=카운터
라인 1: {printf "%s",(NF==1?$0 FS:(c==0?"":RS) $0 RS)}
: 연산의 경우 중첩된 삼항
#Single ternary if operation:
condition?true action:false action
#Nested if operations:
condition1?true action 1:(condition2:true action2:false action2) #nested ternary if operations
-------------------------[ ^ false action1 ^ ]
이는 의사 코드로 설명할 수 있습니다. 예를 들면 다음과 같습니다.
if NF==1 then print $0 and print FS
else (if c==0 then print "" else print RS) and print $0 and print RS again
2호선: {(NF==1?++c:c=0)}
: 또 다른 삼항 if 연산으로 다음과 같이 표현할 수 있습니다.
If NF==1 (line has one field)
then increase counter c by one
else reset counter c.
3행: c==4{printf "\n";c=0}
클래식 awk 구문:condition{action}
If counter c==4 then print a new line and reset counter c
4행: END{printf "\n"}' file
: 스크립트 끝에 새 줄을 인쇄합니다.
답변2
다음 방법을 사용하여 sed
원하는 것을 얻을 수 있습니다.
sed -e '
/./!b
/[^[:space:]]/!b
/[^[:space:]][[:blank:]]\{1,\}[^[:space:]]/b
:loop
$q;N
/\n.*\S[[:blank:]]\+\S/b
s/\n/ /;tdummy
:dummy
s/[[:space:]]\{1,\}/&/3;t
bloop
' yourfile
설명하다
- 빈 칸, 공백, NF > 1줄을 건너뜁니다.
- 패턴 공간에 단일 필드 행이 포함된 do-while 루프를 설정합니다.
- 다음 줄을 잡고 NF > 1인지 확인합니다. 이 시점에서 전체 패턴 공간을 인쇄하고 다음 줄 읽기로 돌아갑니다.
- 이제 우리는 다음 줄도 단일 필드라는 것을 알고 있으므로 계속해서 패턴 공간의 두 부분을 연결하는 개행 문자를 잘라냅니다.
- 패턴 공간에 스페이스 블록이 3개 있나요? 그렇다면 전체 패턴 공간을 인쇄하고 다음 줄을 읽기 시작합니다.
- 그렇지 않으면 다음 줄을 순차적으로 읽지만 이를 기존 패턴 공간에 추가하는 루프로 다시 분기됩니다.
결과
1
4 5 6 7 19
20 22
24 26 27
29 30 31 32
34 40 50 56
58 100
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307
2309
답변3
용법: ./join_rows.awk input.txt
시스템에 따라 위치가 다를 수 있으므로 #!/usr/bin/awk -f
shebang 을 확인하세요 .awk
#!/usr/bin/awk -f
BEGIN {
count = 1;
}
{
if (NF == 1) {
if (count > 1 && count <= 4) printf " ";
printf "%s", $1;
count++;
if (count > 4) {
printf "\n";
count = 1;
}
} else {
if (count > 1) printf "\n";
print;
count = 1;
}
}
END {
if(count > 1) printf "\n";
}
산출:
1
4 5 6 7 19
20 22
24 26 27
29 30 31 32
34 40 50 56
58 100
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307
2309
답변4
확장하다멍하니방법:
columns.awk 재정렬스크립트:
#!/bin/awk -f
function printRow(a, i, v)
{
for (i in a) {
printf "%s ", a[i]
}
print ""
delete a
}
NF <= 2{
for (i=1; i<=NF; i++) {
a[++c] = $i
if (length(a) == 4) {
c = 0
printRow(a)
}
}
}
NF > 2{
if (length(a) > 0) {
c = 0
printRow(a)
}
print $0
}
END{ print }
용법:
awk -f rearrange_columns.awk yourfile
산출:
1
4 5 6 7 19
20 22
24 26 27
29 30 31 32
34 40 50 56
58 100
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307
2309