파일의 줄 순서 변경

파일의 줄 순서 변경

특정 패턴의 줄 순서를 변경하려고 합니다. 줄이 많은 파일(예: 99줄)로 작업합니다. 세 줄마다 두 번째 줄을 세 번째 줄로, 세 번째 줄을 두 번째 줄로 하고 싶습니다.

예.

1- 입력:

gi_1234
My cat is blue.
I have a cat.
gi_5678
My dog is orange.
I also have a dog.
...

2- 출력:

gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.
...

답변1

$ seq 9 | sed -n 'p;n;h;n;G;p'
1
3
2
4
6
5
7
9
8

즉, p현재 라인을 린트하고, n확장 라인을 얻고, h오래된 라인을 얻고, n확장 라인을 얻고, G유지된 라인을 얻고(패턴 공간에 추가), p세 번째 라인과 두 번째 라인을 교체하여 2라인 패턴 공간을 린트합니다.

답변2

awk정수 수학 사용 :

awk 'NR%3 == 1 { print } NR%3 == 2 { delay=$0 } NR%3 == 0 { print; print delay; delay=""} END { if(length(delay) != 0 ) { print delay } }' /path/to/input

모듈러스 연산자는 정수 나누기를 수행하고 나머지를 반환하므로 각 줄에 대해 시퀀스 1, 2, 0, 1, 2, 0 [...]을 반환합니다. 이를 알고 있으면 나중을 위해 모듈러스가 2인 라인에 입력을 저장합니다. 즉, 입력이 0일 때 입력을 인쇄한 직후입니다.

답변3

사용 perl및 짧은 스크립트:

user@pc:~$ cat input.txt 
gi_1234
My cat is blue.
I have a cat.
gi_5678
My dog is orange.
I also have a dog.

user@pc:~$ perl -ne '$l2=<>; $l3=<>; print $_,$l3,$l2;' input.txt 
gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.

스크립트는 전체 파일을 처리하며, ( 에 저장된 $_) 각 줄에 대해 다음 두 줄( $l2$l3)을 가져와서 요청한 순서대로 인쇄합니다: line1, line3, line2.

답변4

perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt

여기서 아이디어는 %줄 번호 $.변수와 함께 모듈로 연산자를 사용하여 어느 것이 첫 번째 줄인지, 어느 것이 두 번째 줄인지, 어느 것이 세 번째 줄마다인지 알아내는 것입니다. 세 번째 줄마다 나머지는 0이고, 첫 번째와 두 번째 줄마다 해당 숫자가 있습니다.

시험:

$ cat input.txt                                                                                                          
gi_1234
My cat is blue.
I have a cat.
gi_5678
My dog is orange.
I also have a dog.

$ perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt                                    
gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.

사소한 개선

두 번째 줄을 변수에 저장하는 접근 방식에는 결함이 있습니다. 마지막 줄이 "두 번째" 줄이면 어떻게 될까요? 즉, 해당 줄 번호의 나머지가 2 인가요? My dog is orange마지막 줄을 생략하면 my 및 DopeGhoti의 답변에 있는 원래 코드가 인쇄되지 않습니다 . 두 경우 모두 이에 대한 수정 방법은 END{}인쇄 후 임시 변수를 설정 해제하여 코드 블록을 사용하는 것입니다. 다시 말해서:

$ awk 'NR%3 == 1 { print } NR%3 == 2 { delay=$0 } NR%3 == 0 { print; print delay;delay=""}END{print delay}' input.txt

그리고

$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s}' input.txt 

이렇게 하면 코드는 3으로 나눌 수 있는 줄뿐만 아니라 파일의 임의 개수의 줄에서도 작동합니다.

댓글에 언급된 문제에 대한 추가 수정

awk의 경우 파일의 마지막 줄에서 $에 대해 1이 출력됩니다. % 3, 이전 코드에는 의 무조건 인쇄로 인해 빈 줄바꿈을 출력하는 문제가 있습니다 . 주석에 언급된 함수는 작동 중인 모든 변수에 항상 줄바꿈을 추가하기 END{print delay}때문입니다 . 버전 print의 경우 플래그 함수를 사용하면 개행 문자를 추가하지 않으므로 perl이 문제가 발생하지 않습니다 .-neprint

그럼에도 불구하고 awk의 경우 수정 사항은 주석에서 Dope Ghoti가 언급한 것처럼 조건부로 만드는 것입니다. 임시 변수의 길이를 확인하는 것입니다. 동일한 수정 사항의 Perl 버전은 다음과 같습니다.

$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s if length $s}' input.txt 

관련 정보