Bash: 줄 번호로 줄 필터링

Bash: 줄 번호로 줄 필터링

행과 열이 많은 구분된 파일( )이 있는 경우 data.txt:

346 dfd asw  34
565 sd  wdew 34
667 ffg wew  23
473 sa  as   21
533 jhf qwe  54

추출하려는 줄 번호가 포함된 다른 파일( positions.txt)

3
5
8

positions.txt이 파일을 사용하여 해당 위치를 추출하려면 어떻게 해야 합니까 data.txt? 다음은 내가 기대하는 결과의 예입니다.

667 ffg wew  23
533 jhf qwe  54

답변1

간단하게awk:

awk 'NR==FNR{ pos[$1]; next }FNR in pos' positions.txt data.txt
  • NR==FNR{ ... }- 첫 번째 입력 파일(예: positions.txt)을 처리합니다.
    • pos[$1]- 누적 위치(레코드 수)를 pos배열 키로 설정
    • next- 다음 레코드로 이동
  • FNR in pos- 두 번째 입력 파일을 처리할 때 data.txt( FNR현재 입력 파일에서 읽은 레코드 수를 나타냄) 현재 레코드 번호가 FNR위치 배열에 있는 경우에만 레코드 인쇄 pos(키로 검색)

예제 출력:

667 ffg wew  23
533 jhf qwe  54
...

답변2

먼저 파일 sed에서 스크립트를 만듭니다.positions.txt

sed 's/$/p/' positions.txt

이것은 출력됩니다

3p
5p
8p

이 간단한 스크립트는 지정된 줄만 인쇄합니다.

data.txt그런 다음 파일 에 적용하십시오 . 사용 중인 경우 bash(또는 프로세스 대체를 이해하는 쉘 <( ... )):

sed -n -f <( sed 's/$/p/' positions.txt ) data.txt

주어진 스크립트에 의해 명시적으로 인쇄된 내용을 제외한 -n모든 출력을 중지합니다 .sedsed

주어진 예를 바탕으로 이것은 다음과 같습니다.

667 ffg wew  23
533 jhf qwe  54

사용하지 않는 bash경우

sed 's/$/p/' positions.txt >filter.sed
sed -n -f filter.sed data.txt
rm -f filter.sed

...똑같은 일을 할 거예요.

답변3

정렬된 경우 전체 저장소 positions.txt없이 두 파일을 동시에 전달하여 이 작업을 수행할 수도 있습니다 . 이전에 일치하는 줄이 충족되면 다음 줄을 읽으세요.positions.txtpositions.txt

$ awk -vpos=positions.txt 'function get() { getline num < pos } 
     BEGIN { get() } NR==num { print; get() }' data.txt                 
667 ffg wew  23
533 jhf qwe  54

실제로 이는 두 파일이 모두 매우 큰 경우에만 작동합니다.진짜충분한 저장.

답변4

간단한 for 루프로 이를 수행할 수 있습니다.

방법 1은 sed와 for 루프를 사용합니다.

for i in `cat positions.txt`; do sed -n ""$i"p" data.txt ; done

산출

667 ffg wew  23
533 jhf qwe  54

방법 2는 awk 및 for 루프를 사용합니다.

for i in `cat positions.txt`; do awk -v i="$i" 'NR==i {print $0}' data.txt ;done

산출

667 ffg wew  23
533 jhf qwe  54

관련 정보