임시 파일을 사용하지 않고 출력의 첫 N 줄을 끝으로 이동


11

다음과 같은 명령의 출력을 상상해보십시오.

44444
55555
11111
22222
33333

첫 번째 N 줄을 잡아 당기고 (위 예제에서 처음 두 줄) 끝에 임시 파일을 추가 하지 않고 어떻게 추가 할 수 있습니까 (파이프 만 사용)?

11111
22222
33333
44444
55555

라인을 따라 뭔가 | sed -n '3,5p;1,2p'(sed로 분명히 작동하지 않는 것은 명령의 순서에 신경 쓰지 않습니다).


2
왜 임시 파일을 사용할 수 없습니까?
Braiam

답변:


13

해당 행을 보류 버퍼에 복사 한 다음 삭제하고 마지막 행에서 보류 버퍼의 내용을 패턴 공간에 추가하십시오.

some command | sed '1,NUMBER{           # in this range
H                                       # append line to hold space and
1h                                      # overwrite if it's the 1st line
d                                       # then delete the line
}
$G'                                     # on last line append hold buffer content

으로 gnu sed당신이로 쓸 수

some command | sed '1,NUMBER{H;1h;d;};$G'

여기 올과 다른 방법 ed(그것 r의 출력 EADS some command텍스트 버퍼를 다음 m라인 oves 1,NUMBER라 후 $t 하나)

ed -s <<IN
r ! some command
1,NUMBERm$
,p
q
IN

지적했듯이 출력에 NUMBER+1 줄 미만이면 둘 다 실패합니다 . 더 확실한 접근법은 다음과 같습니다 ( gnu sed구문).

some command | sed '1,NUMBER{H;1h;$!d;${g;q;};};$G'

이 줄은 마지막 줄 ( $!d) 이 아닌 한 해당 범위의 줄만 삭제합니다. 그렇지 않으면 보류 버퍼 내용 ( g)으로 패턴 공간을 덮어 쓴 다음 q현재 패턴 공간을 인쇄 한 후 uits를 덮어 씁니다 .


2
sed -e '1,NUMBER{H;1h;d;}' -e '$G'또한 이식 가능하게 작동합니다 (일부 sed구현에서는 보류 공간에 몇 킬로바이트 이상을 보유 할 수 없으므로 NUMBER 는 너무 클 수 없습니다)
Stéphane Chazelas

@ StéphaneChazelas-입력 주셔서 감사합니다-일반적으로 휴대가 가능하다는 것을 알고 있기 때문에 한 줄에 하나의 명령을 사용합니다. 여러 표현식 구문은 항상 약간 혼란 스럽습니다. 예를 들어 posix 문서는 "<right-brace> 앞에 <newline> "붙어 있어서 그렇게해서는 안됩니다 sed -e '1,NUMBER{H;1h;d' -e'}' -e '$G'.
don_crissti

4
일반적으로 새로운 -e줄 바꿈이 바뀝니다. d;}POSIX는 아니지만 휴대용입니다. 다음 POSIX 사양에서 수정 될 것입니다. austingroupbugs.net/view.php?id=944#c2720
Stéphane Chazelas

2
@don_crissti 감사합니다! 왜 작동하는지에 대한 간단한 설명을 포함시킬 수 있다면 좋을 것입니다. (물론 찾아 보 겠지만 더 가치있는 답이 될 것입니다.)
Peter Uhnak

내 머리에, 이식 할 수 1,NUMBER{H;1h;d;}없는 것은 여는 중괄호 바로 뒤에 세미콜론이 없다는 것 입니다. sed20 년 후에도 해결 방법이 여전히 내 손가락에 연결되어 있는 SunOS 4.1 의 버그 일 수 있습니다 .
zwol


6

나는 이것을 가지고 xclip이렇게 할 수 있습니다 :

./a_command | xclip -in && xclip -o | tail -n +3 && xclip -o | head -n 2

설명은 다음과 같습니다.

xclip - command line interface to X selections (clipboard)

NAME
       xclip - command line interface to X selections (clipboard)

SYNOPSIS
       xclip [OPTION] [FILE]...

DESCRIPTION
       Reads from standard in, or from one or more files, and makes the data available as an X selection for pasting into X applications. Prints current X selection to standard out.

       -i, -in
              read text into X selection from standard input or files (default)

       -o, -out
              prints the selection to standard out (generally for piping to a file or program)

3
xclip을 창의적으로 사용하는 데 +1 대답은 액세스 가능한 X 서버가 필요합니다.
jofel

3

펄 방식 :

perl -ne '$.<3?($f.=$_):print;}{print $f'

또는 덜 암호 적으로 작성된 동일한 내용 :

perl -ne 'if($.<3){ $f.=$_ } else{ print } END{print $f}'

예를 들면 다음과 같습니다.

$ cat file
44444
55555
11111
22222
33333

$ cat file | perl -ne '$.<3?($f.=$_):print;}{print $f'
11111
22222
33333
44444
55555

설명

  • -ne: 입력 파일 / 스트림을 한 줄씩 읽고 -e각 줄에 지정된 스크립트를 적용하십시오 .
  • $.<3: $.는 현재 행 번호이므로 3이동하려는 행 수로 변경 하십시오.
  • $.<3?($f.=$_):print;:이 조건 연산자는 일반적인 형식은,이다 condition ? case1 : case2, 그것은 실행 case1하면 condition참이고 case2거짓 일 경우. 여기서 현재 줄 번호가 3보다 작 으면 현재 줄 ( $_)을 변수에 추가 $f하고 줄 번호가 3보다 크면 인쇄합니다.
  • }{ print $f: }{는 perl 속기입니다 END{}. 모든 입력 라인이 처리 된 후에 실행됩니다. 이 시점에서 우리는 이동하려는 모든 줄을 모으고 남겨두고 싶은 모든 줄을 인쇄 할 것 $f입니다.

1
골프 버전과 관련하여 몇 가지 캐릭터를 제거 할 수 있습니다perl -ne '$.<3?$f.=$_:print}{print $f
123

1

POSIX를 사용하십시오 ex. 예, 파일 편집 용이지만 파이프 라인에서 작동합니다.

printf %s\\n 111 222 333 444 555 | ex -sc '1,2m$|%p|q!' /dev/stdin

파이프 라인의 시작 또는 끝에 임의의 명령을 추가 할 수 있으며 동일하게 작동합니다. 더 나은 /dev/stdin점은 POSIX를 준수한다는 점입니다.

( /dev/stdinPOSIX에 지정되어 있는지 여부 는 알 수 없지만 Linux와 Mac OS X에 모두 표시되어 있습니다.)

이것은 sed홀드 스페이스 를 사용하는 것보다 가독성이 뛰어 ex납니다. "이 라인을 끝까지 이동하십시오" 라고 말하면 됩니다. (나머지 명령은 "버퍼 인쇄"및 "종료"를 의미하며, 읽기도 가능합니다.)

NB : ex입력으로 2 줄 미만을 제공하면 위에 제공된 명령이 실패합니다.

더 읽을 거리 :


0

짧은 python스 니펫 :

#!/usr/bin/env python3
import sys
file_ = sys.argv[1]
lines = int(sys.argv[2])
with open(file_) as f:
    f = f.readlines()
    out = f[lines:] + f[:lines]
    print(''.join(out), end='')

파일 이름을 첫 번째 인수로 전달하고 줄 수를 두 번째 인수로 전달하십시오.

예:

$ cat input.txt
44444
55555
11111
22222
33333

$ ./sw_lines.py input.txt 2
11111
22222
33333
44444
55555

$ ./sw_lines.py input.txt 4
33333
44444
55555
11111
22222

0

전체 출력을 메모리에 저장할 수있는 경우 :

data=$(some command)
n=42                  # or whatever
{ tail -n +$((n+1)) <<<"$data"; head -n $n <<<"$data"; } > outputfile

0

GNU가 필요한 다른 옵션은 다음과 같습니다 sed.

(x=$(gsed -u 3q);cat;printf %s\\n "$x")

-u명령이 STDIN의 3 줄 이상을 소비하지 않도록 GNU를 sed버퍼링 sed하지 않습니다. 명령 대체는 빈 행을 제거하므로, 세 번째, 세 번째 및 두 번째 또는 세 번째, 두 번째 및 첫 번째 행이 비어있는 경우 명령 끝에 출력 끝에 빈 행이 포함되지 않습니다.

다음과 같이 할 수도 있습니다 :

tee >(sponge /dev/stdout|sed -u 3q)|sed 1,3d

sponge /dev/stdout|명령이 없으면 긴 입력으로 실패합니다. 예를 들어 입력이 줄 바꿈 인 위치 에있는 경우 또는로 끝나는 경우에도 입력 끝에서 빈 줄이 제거 되는 경우 에도 인쇄 sponge /dev/stdout할 수 있습니다 . 위의 명령은 입력 행 수가 하나 또는 두 개일 때 첫 번째 행을 삭제합니다.tac|taca\ncba\nb\nc\n(x=$(cat);printf %s\\n "$x")

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.