STDOUT의 n 번째 라인을 가져 오는 명령


210

STDOUT의 n 번째 줄을 가져올 수있는 bash 명령이 있습니까?

즉, 이것을 취할 무언가

$ ls -l
-rw-r--r--@ 1 root  wheel my.txt
-rw-r--r--@ 1 root  wheel files.txt
-rw-r--r--@ 1 root  wheel here.txt

그리고 같은 일을

$ ls -l | magic-command 2
-rw-r--r--@ 1 root  wheel files.txt

나는 재사용 할 스크립트를 작성할 때 이것이 나쁜 습관이라는 것을 알고 있지만, 매일 쉘을 사용할 때 STDOUT을 필터링하는 것이 유용 할 것입니다.

또한 이것이 (버퍼 STDOUT, 특정 행을 반환) 작성하는 반 사소한 명령이라는 것을 알고 있지만 스크립트를 제자리에 놓지 않고 사용할 수 있는 표준 쉘 명령 이 있는지 알고 싶습니다 .


5
방금 단어를 사용하여 투표했습니다magic-command
Sevenearths

답변:


332

사용 sed다만 다양한 :

ls -l | sed -n 2p

필요한 라인이 인쇄 될 때 입력을 읽지 않기 때문에보다 효율적인이 대안을 사용하면 급지 과정에서 SIGPIPE가 생성되어 원치 않는 오류 메시지가 생성 될 수 있습니다.

ls -l | sed -n -e '2{p;q}'

lsSIGPIPE를 얻었을 때 불평하는 명령이 아니지만 일반적으로 첫 번째를 사용하기에 충분하다는 것을 알았습니다 (어쨌든 입력하기 쉽습니다) .

다양한 라인의 경우 :

ls -l | sed -n 2,4p

여러 줄 범위의 경우 :

ls -l | sed -n -e 2,4p -e 20,30p
ls -l | sed -n -e '2,4p;20,30p'

p는 무엇을 의미합니까? 2p 3p처럼? 의미에서 나는 그것이 2/3 줄에 대한 것이라는 것을 이해하지만 그 뒤에있는 이론 / 이해는 무엇입니까?
Leo Ufimtsev

4
@LeoUfimtsev :는 앞에 나오는 행 범위로 식별되는 행을 인쇄 p하는 sed명령문입니다. 따라서 2,4p인쇄 라인 2, 3, 4를 의미합니다.
Jonathan Leffler

3
그리고 n다른 모든 줄을 인쇄하지 않는 것을 의미합니다
Timo

85
ls -l | head -2 | tail -1

13
+2, 그러나 나는 제안한다 head -n 2 | tail -n 1– 현대 머리와 꼬리는 그렇지 않으면 경고를 발하는 경향이있다.
Michael Krelin-해커

2
두 가지 프로세스를 사용하여 데이터를 필터링하는 것은 약간의 과잉입니다 (그러나 오늘날 기계의 성능을 고려할 때 아마도 대처할 것입니다). 하나의 범위를 처리하기위한 일반화는 사소한 것이 아니며 (범위 N..M의 경우 사용 head -n M | tail -n M-N+1) 여러 범위를 처리하기위한 일반화는 불가능합니다.
Jonathan Leffler

3
머리가 꼬리에 파이프? 끔찍한. 여러 가지 더 나은 방법.
camh September

16
* nix에서 스크립트 명령 행에 대한 좋은 점 : 모두 만 한 모든 것을 모든 사람들의이 좋아하는 가지고 할 수있는 방법과 미워 다른 방법이 ... :-)
beggs

1
라인의 범위 다른 방법을 인쇄하는 방법 : $ ls -l | awk '{if (NR>=4 && NR<=64) print}'(... 등 쉽게 이상의 조건, 여러 범위를 추가 할 수 있습니다)
user10607

41

좋은 머리 / 꼬리 방법의 대안 :

ls -al | awk 'NR==2'

또는

ls -al | sed -n '2p'

1
내 awk가 더 좋지만 sed는 좋습니다.
Michael Krelin-해커

"if"가 필요 없음-해커의 답변을 참조하십시오 ( 시스템에서 모든 파일을 찾는 것에 대한 부분은 제외 ). ;-)
추후 공지가있을 때까지 일시 중지되었습니다.

무엇 '2p'을 의미합니까?
파쇄

1
@shredding 짧은 답변 인쇄 두 번째 줄; long-> 사용될 경우, 패턴과 일치하는 행만 주소 뒤에 명령이 제공됩니다. 간단히 말해서 / p 플래그와 함께 사용하면 일치하는 줄이 두 번 인쇄됩니다 (sed '/ PATTERN / p'파일). 물론 패턴은 정규식
Medhat

만약에 2변수는? 모든 예제는 작은 따옴표를 사용하지만 var에는 큰 따옴표가 필요합니다. vars를 사용할 때 작은 따옴표로도 작동하도록 awk를 "프로그램"할 수 있습니까? 예 line =1; ls | awk 'NR==$line'. 나는 bashvars와 함께 큰 따옴표 를 사용 한다는 것을 알고 있습니다.
Timo

21

에서 sed1line :

# print line number 52
sed -n '52p'                 # method 1
sed '52!d'                   # method 2
sed '52q;d'                  # method 3, efficient on large files

에서 awk1line :

# print line number 52
awk 'NR==52'
awk 'NR==52 {print;exit}'          # more efficient on large files

9

완전성을 위해 ;-)

더 짧은 코드

find / | awk NR==3

짧은 수명

find / | awk 'NR==3 {print $0; exit}'

당신은 완전성에 대해 농담하지 않습니다!
추후 공지가있을 때까지 일시 중지되었습니다.

나는 ;-) 아니에요. 사실, 나는 왜 모든 사람이 사용하는지 모르겠습니다 ls. 원래 질문은 누군가에 관한 STDOUT것이 었으므로 더 큰 것을 갖는 것이 더 낫다고 생각했습니다.
Michael Krelin-해커

적어도 GNU awk의 경우 기본 동작은 { print $0 }이므로`awk 'NR == 3'은 더 짧은 방법입니다.
ephemient

해당 조치에 "; exit"를 추가해야합니다. 나머지 줄을 처리하지 않아도 나머지 줄을 처리 할 필요가 없습니다.
camh

@camh : "공급 프로세스에서 SIGPIPE를 생성하여 원치 않는 오류 메시지가 생성 될 수 있습니다"에 대한 Jonathan Leffer의 답변을 참조하십시오.
ephemient


6

awk를 사용할 수 있습니다 :

ls -l | awk 'NR==2'

최신 정보

위의 코드는 한 번의 오류로 인해 원하는 것을 얻지 못합니다. ls -l 명령의 첫 번째 행은 행입니다. 이를 위해 다음과 같이 수정 된 코드가 작동합니다.

ls -l | awk 'NR==3'

4

Perl을 쉽게 이용할 수 있습니까?

$ perl -n -e 'if ($. == 7) { print; exit(0); }'

7을 원하는 숫자로 대체하십시오.


가장 쉬운 내가이 후 개인적으로 사용했던 일반화 될 것으로 보인다 이후이 내 즐겨 찾기입니다 n 번째는, 펄 -n -e '경우 ($ % 7 == 0.) {인쇄; 이탈 (0); } '
mat kelcey

@matkelcey는 $ awk 'NR % 7' filename파일의 모든 7 번째 줄을 인쇄하도록 할 수도 있습니다 .
user10607

3

다른 포스터 제안

ls -l | head -2 | tail -1

그러나 헤드를 테일에 파이프하면 라인 N까지의 모든 것이 두 번 처리되는 것처럼 보입니다.

머리에 꼬리를 배관

ls -l | tail -n +2 | head -n1

더 효율적일까요?


0

예, Jonathan Leffler가 이미 지적한 것처럼 가장 효율적인 방법은 sed를 print & quit과 함께 사용하는 것입니다.

set -o pipefail                        # cf. help set
time -p ls -l | sed -n -e '2{p;q;}'    # only print the second line & quit (on Mac OS X)
echo "$?: ${PIPESTATUS[*]}"            # cf. man bash | less -p 'PIPESTATUS'

pipefail과 PIPESTATUS의 사용은 매우 흥미롭고이 페이지에 많은 것을 추가합니다.
Mike S

0

내 경우에는 sed가 작동하지 않았습니다. 내가 제안:

"odd"라인 1,3,5,7 ... ls | awk '0 == (NR + 1) % 2'

"짝수"라인의 경우 2,4,6,8 ls | awk '0 == (NR) % 2'


-1

더 완전성을 위해 ..

ls -l | (for ((x=0;x<2;x++)) ; do read ; done ; head -n1)

두 번째 줄에 도달 할 때까지 줄을 버리십시오. 그런 다음 첫 줄을 인쇄하십시오. 따라서 세 번째 줄을 인쇄합니다.

두 번째 줄이면 ..

ls -l | (read; head -n1)

필요한만큼 '읽기'를 넣습니다.


-1

나는 이것을 .bash_profile에 추가했다.

function gdf(){
  DELETE_FILE_PATH=$(git log --diff-filter=D --summary | grep delete | grep $1 | awk '{print $4}')
  SHA=$(git log --all -- $DELETE_FILE_PATH | grep commit | head -n 1 | awk '{print $2}')
  git show $SHA -- $DELETE_FILE_PATH
}

그리고 그것은 작동합니다

gdf <file name>

나는 의아해한다 – 이것이 질문과 어떤 관계가 있는가?
Jonathan Leffler
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.