![파일에서 일정한 간격의 줄을 병합하는 방법은 무엇입니까?](https://linux55.com/image/95229/%ED%8C%8C%EC%9D%BC%EC%97%90%EC%84%9C%20%EC%9D%BC%EC%A0%95%ED%95%9C%20%EA%B0%84%EA%B2%A9%EC%9D%98%20%EC%A4%84%EC%9D%84%20%EB%B3%91%ED%95%A9%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
내용이 다음과 같은 파일이 있습니다.
a1
b1
c1
aa
bb
cc
aaa
bbb
ccc
d1
e1
f1
dd
ee
ff
ddd
eee
fff
g1
h1
i1
gg
hh
ii
ggg
hhh
iii
고정된 간격(이 경우 3)으로 행을 병합하고 다음과 같은 결과를 얻는 가장 좋은 방법은 무엇입니까?
a1 aa aaa
b1 bb bbb
c1 cc ccc
d1 dd ddd
e1 ee eee
f1 ff fff
g1 gg ggg
h1 hh hhh
i1 ii iii
입력에서 출력을 얻는 알고리즘은 다음과 같습니다.
- 먼저 행 1, 즉 a1을 얻습니다.
- 우리는 간격이 3이라는 것을 알고 있습니다.
- 따라서 1행, 1+3행, 1+3+3행은 같은 행에 있어야 합니다.
- 마찬가지로 라인 2, 5, 8도 같은 라인에 있어야 합니다.
그것들a1,아그리고아아아등은 임의의 더미 텍스트일 뿐이며 임의의 문자열일 수 있습니다. 요점은 둘 사이에 고정된 간격이 있다는 것입니다.a1,아그리고아아아.
현재 나는 이 작업을 수행하기 위해 emacs 키보드 매크로를 사용합니다. 그래도 이 문제를 해결하는 더 좋은 방법이 있는지 알고 싶습니다. 미리 감사드립니다.
답변1
/anything 에 있고 gnu
행 수가 9의 배수인 경우 다음을 실행할 수 있습니다.
split -l9 --filter='pr -3 -s" " -t' infile
이렇게 하면 입력이 9개의 행으로 분할되고 각 행은 pr -3 -s" " -t'
숫자에 따라 열로 연결됩니다. 선과 길이에 대해서는 및 pr
옵션을 사용해야 할 수도 있습니다 . 자세한 내용은 페이지를 참조하세요 .-w
-l
man
답변2
다음은 세 줄로 구분된 세 그룹을 추출하기 위해 하드 코딩된 awk의 간단한 솔루션입니다.
{
if (NR > 1 && (NR % 9) == 0) {
print a "\n" b "\n" c " " $0
a=""
b=""
c=""
} else if (NR % 3 == 1) {
if (NR % 9 > 1) {
a=a" "$0
} else {
a=$0
}
} else if (NR % 3 == 2) {
if (NR % 9 > 2) {
b=b" "$0
} else {
b=$0
}
} else {
if (NR % 9 > 3) {
c=c" "$0
} else {
c=$0
}
}
}
파일로 저장하고 실행해 보세요 awk -f thatfile < input
. 이 작업을 수행하는 더 현명한 방법이 있다고 확신하지만 매일 awk에서 작업하지는 않습니다.
답변3
이것은 약간 까다롭습니다. 이 작업을 수행할 수 있는 유틸리티는 없습니다.
파이프라인은 (기본적으로) 한 번에 9개의 행을 읽고 이를 사용하여 pr
3개의 열로 형식을 지정합니다.
# there are 9 single hyphens below
paste -d: -- - - - - - - - - - < file | while read line; do
tr : '\n' <<<"$line" | pr -s" " -T -3
done
a1 aa aaa
b1 bb bbb
c1 cc ccc
d1 dd ddd
e1 ee eee
f1 ff fff
g1 gg ggg
h1 hh hhh
i1 ii iii
이는 실제 텍스트에 콜론이 없다고 가정합니다.
답변4
매우 간단하고 명확한 방법TxR:
@(repeat)
@x0
@x1
@x2
@y0
@y1
@y2
@z0
@z1
@z2
@ (output)
@x0 @y0 @z0
@x1 @y1 @z1
@x2 @y2 @z2
@ (end)
@(end)
달리기:
$ txr reshape.txr data
a1 aa aaa
b1 bb bbb
c1 cc ccc
d1 dd ddd
e1 ee eee
f1 ff fff
g1 gg ggg
h1 hh hhh
i1 ii iii
압축하는 방법에는 여러 가지가 있지만 이를 이해하려면 다음과 같이 더 열심히 노력해야 합니다.
@(repeat)
@ (collect :times 9)
@line
@ (end)
@ (bind (x y z) @(tuples 3 line))
@ (output)
@ (repeat)
@x @y @z
@ (end)
@ (end)
@(end)
또한 Awk의 작업에 대해 조금 아는 사람들은 이를 구현할 수 있습니다.
{ a[(NR-1)%9] = $0 }
!(NR%9) { print a[0], a[3], a[6]
print a[1], a[4], a[7]
print a[2], a[5], a[8] }
산출:
$ awk -f reshape.awk data
a1 aa aaa
[ ... ]
i1 ii iii
코더가 반복되는 print
패턴이 부적절하다고 판단하는 경우:
{ a[(NR-1)%9] = $0 }
!(NR%9) { for (i = 0; i < 3; i++)
print a[i], a[i+3], a[i+6] }
TXR Lisp 솔루션:
[(opip (tuples 3) (tuples 3) (mappend transpose)
(mapcar (aret `@1 @2 @3`)) tprint)
(get-lines)]
달리기:
$ txr reshape.tl < data
명령줄에서: 사용 -t
, 제거 tprint
:
$ txr -t '[(opip (tuples 3) (tuples 3) (mappend transpose)
(mapcar (aret `@1 @2 @3`)))
(get-lines)]' < data
이는 입력을 트리플로 지원하는 파이프라인에 입력한 다음 해당 트리플 중 트리플(기본적으로 중첩 목록으로 구성된 3x3 행렬)을 지원함으로써 수행됩니다. 이러한 행렬은 개별적으로 전치된 다음 해당 행이 함께 추가되어 거대한 트리플 목록을 형성합니다. 이러한 트리플은 aret
연산자 문자열 보간법을 부분적으로 적용하여 문자열로 변환되며, 출력은 tprint
문자열 목록을 출력할 라인으로 처리합니다. 문법
(aret `@1 @2 @3`)
다음과 같이 확장됩니다.
(lambda (. args)
(apply (lambda (arg1 arg2 arg3)
`@arg1 @arg2 @arg3`)
args))
기본적으로 인수를 3개 인수 익명 함수에 적용할 매개변수 목록으로 처리하는 1개 인수 익명 함수를 암시적으로 생성합니다. 여기서 , 는 @1
인수 @2
를 @3
나타냅니다. 함수 본문은 이러한 특수 숫자 인수를 기계 생성 인수 이름으로 대체하여 원래 준 문자열 표현식에서 파생됩니다.