우분투 터미널을 사용하고 있는데 파일의 특정 줄(11번째 위치)을 첫 번째 줄로 이동한 다음 최종 결과를 새 파일로 전송해야 합니다. 원본 파일에는 수백 줄이 포함되어 있습니다.
지금까지 sed 명령 도구를 사용해 보았지만 원하는 효과를 얻지 못했습니다. 이것이 내가 지금까지 얻은 것입니다:
[mission 09] $ sed -n -e '1p' -e '11p' bonjour > bonjour2
하지만 새 파일에서는 첫 번째 줄과 11번째 줄만 표시됩니다. 하지만 새 파일이 나머지 원본 줄과 함께 원하는 개정 위치를 갖기를 원합니다.
입력하다:
English: Hello
Turkish: Marhaba
Italian: Ciao
German: Hallo
Spanish: Hola
Latin: Salve
Greek: chai-ray
Welsh: Helo
Finnish: Hei
Breton: Demat
French: Bonjour
원하는 출력
French: Bonjour
English: Hello
Turkish: Marhaba
Italian: Ciao
German: Hallo
Spanish: Hola
Latin: Salve
Greek: chai-ray
Welsh: Helo
Finnish: Hei
Breton: Demat
어떤 제안이 있으십니까?
답변1
사용(및 ed
파생된 줄 편집기):sed
grep
printf '%s\n' '11m0' 'w bonjour2' 'q' | ed -s bonjour
11m0
이렇게 하면 파일에 편집 명령이 적용되어 첫 번째 줄 앞으로 11번째 줄이 이동됩니다. 그런 다음 생성된 문서를 파일에 쓰고 bonjour2
종료됩니다.
또는:
printf '%s\n' '11m0' ',p' 'Q' | ed -s bonjour >bonjour2
...명령을 사용하여 특정 파일에 쓰는 대신 ed
전체 파일을 표준 출력으로 인쇄합니다. 그런 다음 결과는 새 파일 이름으로 리디렉션됩니다. 이 ,p
명령(약어로 약칭 1,$p
)은 전체 문서를 표준 출력으로 출력하고 Q
강제 종료합니다(문서가 변경된 경우에도).
문서를 제자리에서 변경하려면(예: 원본 파일 변경) 결과를 파일 자체에 다시 씁니다.
printf '%s\n' '11m0' 'wq' | ed -s bonjour
위 변형 중 하나의 실행 예:
$ printf '%s\n' '11m0' ',p' 'Q' | ed -s bonjour >bonjour2
$ cat bonjour2
French: Bonjour
English: Hello
Turkish: Marhaba
Italian: Ciao
German: Hallo
Spanish: Hola
Latin: Salve
Greek: chai-ray
Welsh: Helo
Finnish: Hei
Breton: Demat
항상 움직여마지막줄을 맨 위로 이동 하려면 $m0
대신 을 사용하세요 11m0
. 항상 문자열로 시작하는 줄을 이동하려면 를 French:
사용하세요 /^French:/m0
.
답변2
sed -n '1h;2,10H;11G;11,$p'
첫 번째 줄은 h
개행으로 인해 복사된 후 H
10에 추가됩니다.
존재하다11번째 줄, 예약된 공간 확보
~에서11 종료하고 인쇄합니다.
]# sed -n '1h;2,10H;11G;11,$p' bonj
French: Bonjour
English: Hello
Turkish: Marhaba
Italian: Ciao
German: Hallo
Spanish: Hola
Latin: Salve
Greek: chai-ray
Welsh: Helo
Finnish: Hei
Breton: Demat
이게 낫다:
]# seq 20 | sed -n '1h;2,10H;11G;11,$p'
11
1
2
3
4
5
6
7
8
9
10
12
13
14
15
16
17
18
19
20
나는 당신을 예로 들어 보겠습니다.
]# sed -e 1p -e 11p -n bonj
English: Hello
French: Bonjour
... -n
끝에 있는 스위치는 두 표현식 모두에 작동한다는 것을 보여주기 위한 것입니다.
나 또한 -n
, 그렇다면 1h;2,10H
이것은 , 이것은 1,10H
, 이것은범위줄 번호 및 "hold"(저장) 명령. 아직 아무것도 인쇄되지 않았습니다.
11,$p
또 다른 범위입니다. 11행에서는 예약 상태(예: 1-10)에서 방금 반환한 내용 "11G"를 인쇄하고 11행에 추가합니다.
$까지의 12번째 줄은 -n
.
나는 -e
당신처럼 두 가지를 해야 합니다:
sed -n -e '1h;2,10H' -e '11G;11,$p'
1,10부터 보류하고 11,$부터 인쇄합니다.
11번째 줄이 먼저 G
이고 그 다음 p
이 중요합니다.
]# seq 20 | sed -n -e '1h;2,10H' -e '11,$p;11G'
11
12
13
14
15
16
17
18
19
20
여기서 12번째 줄은 11번째 줄에 인쇄된 내용을 지웁니다.
매개변수가 있는 함수로
11번째 줄은 "putfirst" 함수 때문에 항상 지루합니다:
]# declare -f putfirst
putfirst ()
{
e="1h;2,$(($1-1))H;${1}G;${1},\$p";
sed -ne "$e" $2
}
두 단계: 문자열 생성, 그 다음 sed 호출. "$"에는 두 가지 의미가 있습니다. "p"는 변수가 아닙니다!
유효한 가장 낮은 숫자는 다음과 같습니다.
]# seq 7 | putfirst 3
3
1
2
4
5
6
7
또는 원본 "bonj" 파일을 사용하세요.
]# putfirst 4 bonj | putfirst 6 |head -4
Latin: Salve
German: Hallo
English: Hello
Turkish: Marhaba
이것은 연속된 두 개의 sed이지만 이제 두 개의 작업이 완료되었습니다.
진주
perl -ne '$n++; $h.=$_ if $n<11; print $_.$h if $n==11; print if $n>11' <(seq 20)
일부 스크립트와 마찬가지로 파일 이름이 필요하고 옵션이 필요하지 않습니다.
$want=11 ;
while (<>) {
$n++ ;
if ($n < $want) # before $want: store line
{ $lowlines .= $_ ;
next } # next line (avoids 'else')
if ($n == $want) # at line $want: append stored lines to $_
{ $_ .= $lowlines }
print ; # print $_ for $n not less than $want
}
AWK(Ed에서 훔친 것입니다(편집자가 아닙니다!))
NR < 11 {
buf[NR] = $0; next
}
NR >=11 {
print
if (NR == 11) {
for (i=1; i<11; i++) { print buf[i] }
}
}
나는 NR
증가 대신에 사용하여 n
프로세스를 더 명확하게 만듭니다. 동일한 "트릭": next
다운스트림을 단순화합니다.
그리고perl -n
$n++ ;
$tmp = $tmp . $_ if $n < 11 ;
print $_ . $tmp if $n == 11 ;
print $_ if $n > 11 ;
이것이 가장 좋은 형식입니다. 대칭.
답변3
내가 올바르게 이해했다면 행 11만 첫 번째 행으로 이동하고 싶을 것입니다.
따라서 원본이 다음과 같다면
Original line 1
Original line 2
...
Original line 18
Original line 19
Original line 20
그러면 결과는
Original line 11
Original line 1
Original line 2
...
Original line 9
Original line 10
Original line 12
Original line 13
...
Original line 19
Original line 20
이는 다음을 통해 달성할 수 있습니다.둘파일을 반복하지만 첫 번째 패스는 짧아질 수 있으므로 너무 끔찍하지는 않습니다.
( sed -n '11 {p;q}' file ; sed 11d file ) > newfile
기본적으로 첫 번째 sed
명령은 11행을 인쇄한 다음 종료됩니다. 두 번째 sed
명령은 각 줄을 인쇄합니다.와는 별개로11호선.
결과적으로 라인 11은 실제로 새 파일의 앞으로 이동됩니다.
답변4
그리고 POSIX sed
:
$ sed -e '1,11!b' -e '11!H;1h;11!d;G' file
사용 perl
:
$ perl -lne '
push(@A,$_),next if $. < 11;
print for $_, splice @A;
' file
사용 bash
:
$ (head -n 11 - | tee log | tail -n 1 -; head -n 10 log; cat -;) < file