cut 출력을 foreach 명령으로 파이프하는 방법은 무엇입니까?

cut 출력을 foreach 명령으로 파이프하는 방법은 무엇입니까?

파일의 각 줄에서 첫 번째 단어를 가져오는 잘라내기 명령이 있습니다. 그런 다음 cut 명령의 각 단어를 foreach에 넣고 싶습니다. 그런 다음 foreach 본문 내에서 grep 명령을 실행하여 다른 파일에서 해당 단어를 grep하려고 합니다.

이 같은:

@array = (cut /tmp/10218.after -f1); 
foreach $word (@lines) { 
   grep $word /tmp/10218.before;
} 

분명히 @array 할당이 작동하지 않습니다. 이 문제를 어떻게 해결할 수 있나요?

나는 그것이 무엇인지, 어느 것이 가장 좋고 충분히 좋은지 모르는 방법이 많이 있다고 확신합니다.

답변1

배쉬에서

while read -r word
do
    grep -q "$word" file.before
    if [ $? -ne "0" ]
    then
        echo "$word not in file"
     fi
done < <(cut -f1 -d" " file.after)

grep 은 -q조용히 하라고 지시한 다음 $?일치하는 항목이 있는지 물어볼 수 있습니다.01

답변2

다음과 같은 작업을 더 수행하고 싶을 것입니다.

for i in $(cat /tmp/10218.after)
do
    grep $(echo ${i} | cut -f1) /tmp/10218.before
done

grep이 실패할 때 좀 더 멋지게 인쇄하고 싶다면 다음과 같이 할 수 있습니다.

for i in $(cat /tmp/10218.after)
do
    COUNT=grep -c $(echo ${i} | cut -f1) /tmp/10218.before
    if [[ ${COUNT} -eq 0 ]]
    then
        echo "${i}: Not Found"
    else
        echo "${i}: Found"
    fi
done

답변3

펄을 사용하세요.

#!/usr/bin/perl

use strict;
use warnings;

my %words_to_find;

open ( my $input, "<", "/tmp/10218.after" );
while ( my $line = <$input> )
{
  my ( $word ) = ( $line =~ m/\A(\S+)\s/ );
  $words_to_find{$word}++;
}
close ( $input );

open ( my $search, "<", "/tmp/10218.before" ); 
while ( my $line = <$search> )
{
  foreach my $word ( key %words_to_find )
  { 
    if ( $line =~ m/$word/ )
    {
      print $line;
      last;
    }
  }
}
close ( $search );

이와 같은 것이 트릭을 수행해야합니다.

답변4

귀하의 코드가 수행하는 작업은 한 파일의 탭으로 구분된 목록에서 첫 번째 필드를 추출한 다음 두 번째 파일에서 해당 단어를 찾으려고 시도하는 것입니다.

단어 목록을 배열에 저장하지 않음으로써 이를 약간 단순화할 수 있습니다.

cut -f1 /tmp/10218.after | grep -f /dev/stdin /tmp/10218.before

그러면 첫 번째 파일에서 단어가 추출되어 grep두 번째 파일과 일치하는 데 사용되는 패턴에 직접 전달됩니다.

그러나 여기서는 몇 가지 최적화를 수행할 수 있습니다. 첫째, 단어 목록에 다음 항목만 포함되어 있는지 확인할 수 있습니다.고유한성격:

cut -f1 /tmp/10218.after | sort -u | grep -f /dev/stdin /tmp/10218.before

grep둘째, 우리는 보장할 수 있습니다문자열 비교정규식 일치 대신:

cut -f1 /tmp/10218.after | sort -u | grep -F -f /dev/stdin /tmp/10218.before

그런 다음 일치하는 부분 문자열을 반환하지 않을 수도 있습니다 grep(예: beein bumblebee).

cut -f1 /tmp/10218.after | sort -u | grep -wF -f /dev/stdin /tmp/10218.before

또한 다음 단어만 일치하는지 확인할 수도 있습니다.첫 번째고정된 정규식으로 단어를 다시 작성하여(및 drop ) -F두 번째 파일에서 열을 제거합니다 .

cut -f1 /tmp/10218.after | sort -u | sed 's/^/^/' | grep -w -f /dev/stdin /tmp/10218.before

sed명령은 ^각 줄의 시작 부분에 삽입되므로 bee문자열 대신 정규식을 얻습니다 ^bee.


또는 하나의 awk프로그램을 사용하여 모든 작업을 수행할 수도 있습니다.

awk -F '\t' 'FNR == NR { words[$1]++; next } words[$1]' /tmp/10218.after /tmp/10218.before

이는 첫 번째 파일의 첫 번째 탭으로 구분된 열을 키로 배열로 읽은 words다음 두 번째 파일에서 해당 키를 기반으로 하는 단어를 확인합니다. 두 번째 파일의 단어가 키로 나타나면 두 번째 파일의 줄을 인쇄합니다.


출력 순서에 신경 쓰지 않으면 다음을 사용할 수도 있습니다 join.

join <( cut -f1 /tmp/10218.after | sort -u -b ) <( sort -b /tmp/10218.before )

bash명령을 작성하는 이 특별한 방법에는 프로세스 대체(예:)를 이해하는 쉘이 필요합니다 <(...).

다른 쉘에서는:

cut -f1 /tmp/10218.after | sort -u -b -o keys
sort -b -o data /tmp/10218.before
join keys data

관련 정보