awk를 사용하여 다른 파일의 숫자를 사용하여 파일에서 줄을 올바르게 추출하려면 어떻게 해야 합니까?

awk를 사용하여 다른 파일의 숫자를 사용하여 파일에서 줄을 올바르게 추출하려면 어떻게 해야 합니까?

나는 bash 쉘을 사용하고 있습니다. 줄 번호가 있는 파일이 있는 경우

1
4
7
9

첫 번째 요소가 숫자이고 그 뒤에 텍스트 문자열이 오는 또 다른 라인 파일

1,Michael Jordan
2,Karl Malone,
3,Charles Barkley
4,Greg Anthony
5,Chris Mullen
6,Reggie Miller
7,Billy Owens
8,David Robinson
9,Shaquille O'Neal
10,John Stockton

awk첫 번째 숫자가 첫 번째 파일에 속하는 경우에만 두 번째 파일에서 줄을 추출하는 명령을 어떻게 작성할 수 있습니까? 위의 예에서는 다음과 같은 결과가 나올 것으로 예상됩니다.

1,Michael Jordan
4,Greg Anthony
7,Billy Owens
9,Shaquille O'Neal

나는 이것을 시도했다

awk 'FNR==NR{a[$1];next} $1 in a' /tmp/first_file /tmp/second_file > /tmp/third_file

그러나 세 번째 파일에서는 아무것도 생성되지 않습니다.

답변1

,두 번째 파일은 쉼표로 구분되므로 명령줄 옵션을 사용하여 awk 필드 구분 기호를 -로 설정해야 합니다 .-F

awk -F, 'FNR==NR{a[$1];next} $1 in a' /tmp/first_file /tmp/second_file > /tmp/third_file

또는 FS내장 변수를 통해:

awk 'FNR==NR{a[$1];next} $1 in a' /tmp/first_file FS=, /tmp/second_file > /tmp/third_file

후자의 접근 방식을 사용하면 첫 번째 파일이 쉼표로 구분되지 않고 여러 필드가 있는 경우를 처리할 수 있습니다.

답변2

사용행복하다(이전 Perl_6)

~$ raku -ne 'BEGIN my @a = "nbr_list.txt".IO.lines.map: *.Int;  \
             .put if $_.split(",")[0] == any(@a);'  file.csv

#OR

~$ raku -ne 'BEGIN my @a = "nbr_list.txt".IO.lines.map: *.Int;  \
             .put if $_.split(",")[0] ~~ any(@a);'  file.csv

Raku는 Perl 계열의 프로그래밍 언어입니다. 숫자 목록을 가져 와서 BEGIN배열에 저장할 때 @a. 그런 다음 플래그는 -ne자동으로 인쇄하지 않고 명령줄에서 파일을 읽습니다( awk유사한 동작).

여기서 행은 테마 변수( $_)(쉼표 위) 로 읽혀지고 split첫 번째 요소( )가 얻어집니다. 숫자 항등 연산자(첫 번째 코드 예) 또는 Raku의 스마트 일치 연산자를 사용하여 [0]이러한 요소를 비교하세요. 연산자 오른쪽에 있는 배열은 노드가 됩니다. 조건이 충족되면 조건에 따라 행이 출력됩니다.==~~@aany()ifput

입력 예:

1,Michael Jordan
2,Karl Malone,
3,Charles Barkley
4,Greg Anthony
5,Chris Mullen
6,Reggie Miller
7,Billy Owens
8,David Robinson
9,Shaquille O'Neal
10,John Stockton

출력 예( nbr_list.txt1,4,7,9로 구성된 파일 사용):

1,Michael Jordan
4,Greg Anthony
7,Billy Owens
9,Shaquille O'Neal

조인 포인트는 자동으로 스레드되기 때문에 흥미롭습니다. 위의 문제에 대해서는 one()커넥터가 더 효율적으로 작동할 수도 있습니다.


또 다른 방법은 집합을 사용하는 것입니다. 즉, 줄 번호를 s로 변환하는 것 Set입니다 Int. 데이터는 행 단위로 읽혀지며, 각 첫 번째 열은 강제로 변환되어 집합의 요소 Int인지 확인됩니다 . (elem)infix (elem)또는 infix , (유니코드 기호)는 다음 코드에서 사용될 수 있습니다.

~$ raku -ne 'BEGIN my $set1 = Set.new("nbr_list.txt".IO.lines.map: *.Int);  \
             .put if $_.split(",").[0].Int (elem) $set1;'  file

Raku 세트는 고유한 값만 포함할 수 있으므로(즉, 입력이 "고유"함) 두 번째 예에서는 파일의 중복 항목을 삭제합니다 "nbr_list.txt". 이것이 실제로 OP가 원하는 것일 수 있습니다.

https://docs.raku.org/type/Junction
https://docs-stage.raku.org/type/Junction
https://raku.org

답변3

이 작업을 "결합"이라고 합니다. coreutils에는 join텍스트 파일을 연결하는 도구가 있습니다 .

join -t, -j1 --nocheck-order first_file second_file
1,Michael Jordan
4,Greg Anthony
7,Billy Owens
9,Shaquille O'Neal

설명하다:

  1. -t,- 필드 구분자로 쉼표를 사용하세요.
  2. -j1- 첫 번째 필드 추가
  3. --nocheck-order- Join을 사용하려면 파일을 정렬해야 하지만 숫자 정렬은 좋아하지 않습니다. 따라서 사전식 순서를 확인하고 "10"이 앞에 오는 "9"에 대해 불평하는 것을 방지합니다. 두 파일의 첫 번째 열이 동일한 알고리즘을 사용하여 정렬되는 한 여전히 작동합니다.

관련 정보