쉘 스크립트 만 사용하여 텍스트 파일에서 특정 줄 가져 오기


100

텍스트 파일에서 특정 줄을 가져 오려고합니다.

지금까지 온라인에서는 sed와 같은 것만 본 적이 있습니다. (저는 sh-bash 나 sed 또는 이와 비슷한 것을 사용할 수 없습니다). 기본 셸 스크립트 만 사용하여이 작업을 수행해야합니다.

cat file | while read line
    do
       #do something
    done

위와 같이 줄을 반복하는 방법을 알고 있지만 특정 줄의 내용 만 가져와야하는 경우


줄 번호를 아십니까?
Mehul Rathod 2013 년

1
그럼 당신은 셀 수 있습니다.
Ignacio Vazquez-Abrams 2013 년

네, 라인 번호는 5입니다 @MehulRathod
GangstaGraham

3
cat괜찮지 만 sed그렇지 않습니까? 말이 안 돼.
William Pursell

5
아무도 거절 할 수 없기 때문 cat입니다. 아 ... 귀여워 cat!

답변:


204

sed :

sed '5!d' file

awk :

awk 'NR==5' file

sh 명령을 사용하면 sed, awk를 사용할 수 없습니다. 나는 질문에서 이것을 더 명확히해야한다.
GangstaGraham

@GangstaGraham 당신은 라인을 반복하는 방법을 알고 있다고 말했습니다. 카운터를 추가하는 것은 어떻습니까? 카운터가 목표 라인 번호에 도달하면 라인을 얻고 루프를 끊으십시오. 도움이 되나요?
Kent

4
@KanagaveluSugumar는 sed의 정보 페이지를 읽었습니다. 5!d5를 제외한 모든 행을 삭제하는 것을 의미합니다. shell var이 가능합니다. 큰 따옴표가 필요합니다.
Kent

13
다른 변형을 추가하는 것이 좋습니다. "기본적으로 출력이 없음"을 의미하고 "인쇄"를 의미하며 잠재적으로 혼란스러운 삭제 언급이 sed -n 5p없기 때문에 초보자를 위해 기억하는 것이 더 논리적으로 보입니다 (사람들이 파일에 대해 이야기 할 때 줄을 삭제하는 경향이 다른 의미). -np
Josip Rodin 2015 년

1
@JosipRodin 당신이 맞아요, -n '5p'이 문제도 해결합니다. 여기서 차이점 은 변경 사항을 파일에 다시 쓰기 위해 5!d추가 할 수 있다는 것 -i입니다. 함께하지만, -n 5p당신이 가지고 sed -n '5p' f > f2&& mv f2 f다시,이 질문에 대해, 나는 당신의 의견에 동의합니다.
Kent

21

line필요한 줄 번호를 보유하는 변수 라고 가정하면 headand 를 사용할 수 있다면 tail매우 간단합니다.

head -n $line file | tail -1

그렇지 않은 경우 작동합니다.

x=0
want=5
cat lines | while read line; do
  x=$(( x+1 ))
  if [ $x -eq "$want" ]; then
    echo $line
    break
  fi
done

-eq비교는 정수에 대한 것이므로 줄 내용 ( $line)이 아닌 줄 번호를 원합니다 . 이것은 예를 들어 want=5루프 이전 에 정의한 다음에 대한 -eq비교 를 사용하여 수정해야 합니다 $want. [거부 된 편집에서 이동 됨]
Josip Rodin

1
@JosipRodin 귀하의 의견에 동의하는대로 독립적 인 편집 제안을했습니다. 이번에는 거부되지 않기를 바랍니다.
Victor Zamanian


11

최고의 성능 방법

sed '5q;d' file

sed5 번째 줄 이후에는 어떤 줄도 읽지 않기 때문에

Roger Dueck 씨의 업데이트 실험

나는 wcanadian-insane (6.6MB)을 설치하고 time 명령을 사용하여 sed -n 1p / usr / share / dict / words와 sed '1q; d'/ usr / share / dict / words를 비교했습니다. 첫 번째는 0.043 초, 두 번째는 0.002 초 였으므로 'q'를 사용하는 것은 확실히 성능 향상입니다!


1
이것은 또한 일반적으로 작성됩니다 :sed -n 5q
William Pursell

3
sed5 번째 줄 이후에는 어떤 줄도 읽지 않기 때문에이 솔루션을 좋아합니다 .
Anthony Geoghegan

1
나는 wcanadian-insane (6.6MB)을 설치 하고 명령을 비교 sed -n 1p /usr/share/dict/words하고 sed '1q;d' /usr/share/dict/words사용했습니다 time. 첫 번째는 0.043 초, 두 번째는 0.002 초 였으므로 'q'를 사용하는 것은 확실히 성능 향상입니다!
Roger Dueck 19-07-04

5

예를 들어 파일의 10 ~ 20 행을 얻으려면 다음 두 가지 방법을 각각 사용할 수 있습니다.

head -n 20 york.txt | tail -11

또는

sed -n '10,20p' york.txt 

p 위의 명령은 인쇄를 의미합니다.

표시되는 내용은 다음과 같습니다. 여기에 이미지 설명 입력


2

이런 일을하는 표준 방법은 외부 도구를 사용하는 것입니다. 쉘 스크립트를 작성하는 동안 외부 도구 사용을 허용하지 않는 것은 어리석은 일입니다. 그러나 외부 도구를 사용하고 싶지 않다면 5 행을 다음과 같이 인쇄 할 수 있습니다.

i=0; while read line; do test $((++i)) = 5 && echo "$line"; done < input-file

이것은 논리 줄 5를 인쇄합니다. 즉, input-file줄 연속이 포함 된 경우 단일 줄로 계산됩니다. -r읽기 명령 에 추가하여이 동작을 변경할 수 있습니다 . (아마 원하는 동작 일 것입니다.)


1
$((++i))수줍음으로 보인다. 영업 외부 도구를 사용하여 제한되어있는 경우, 나는 그들이 이상의 일반에 액세스해야합니다 가정하지 것이다/bin/sh
요시프 로댕

@JosipRodin 아니요, POSIX 기능입니다 (그러나 ++증분 지원 은 특히 ​​선택 사항으로 표시됨).
tripleee

@tripleee / bin / sh로 현대 대시와 함께 작동하지 않으므로 의존하지 않을 것입니다.
Josip Rodin 2015 년

그러나 $((i+=1))Dash에서도 작동하는 것과 같은 간단한 해결 방법 입니다.
tripleee 2015 년

$(($i+1))내가 생각했던 간단한 해결 방법입니다.
Josip Rodin 2015 년

1

William Pursell의 답변 과 병행 하여 원래 v7 Bourne 셸에서도 작동해야하는 간단한 구조가 있습니다 (따라서 Bash를 사용할 수없는 곳도 있음).

i=0
while read line; do
    i=`expr "$i" + 1`
    case $i in 5) echo "$line"; break;; esac
done <file

break우리가 찾고 있던 라인을 얻었을 때 루프 외부로 의 최적화도 주목하십시오 .


0

나는 특별히 어떤 답변도 마음에 들지 않았습니다.

내가 한 방법은 다음과 같습니다.

# Convert the file into an array of strings
lines=(`cat "foo.txt"`)

# Print out the lines via array index
echo "${lines[0]}"
echo "${lines[1]}"
echo "${lines[5]}"

-1

Perl로 쉽게! 파일에서 1, 3, 5 행을 얻으려면 / etc / passwd라고 말하십시오.

perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd

seq 5 | perl -ne 'print if $. ~~ [1, 4, 5]'하지만 smartmatch는 실험적이며 사용을 권장하지 않습니다
Sorin

다른 솔루션 중 하나도 이렇게 간결하지 않거나 이처럼 많은 유연성을 허용하지 않습니다. (왜 시간을 절약하고 일을 더 쉽게 만드는 모든 것이 "똑똑한 사람들"에 의해 "낙담"하는
것처럼 보

-1
line=5; prep=`grep -ne ^ file.txt | grep -e ^$line:`; echo "${prep#$line:}"

3
질문을 한 사람에게 더 명확하게하기 위해이 작업이 왜 작동하는지 조금이라도 설명해 주시겠습니까?
ted

따라서 첫 번째 grep은 시작 부분에 줄 번호를 추가하는 모든 줄을 선택합니다. 그런 다음 두 번째 grep은 시작할 때 줄 번호를 일치시켜 특정 줄을 선택합니다. 그리고 마지막으로 줄 번호는 에코에서 줄 시작부터 잘립니다.
Oder

이것은에 비해 복잡하고 비효율적 sed -n 5p입니다. 물론 여전히 다음과 같이 최적화 할 수 있습니다sed -n '5!d;p;q'
tripleee
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.