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

あなたのコードが行うことは、1つのファイルのタブで区切られたリストから最初のフィールドを抽出し、2番目のファイルでその単語を見つけようとすることです。

単語リストを配列に保存しないことで、これを少し単純化できます。

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

その後、最初のファイルから単語が抽出され、grep2番目のファイルと一致するために使用されるパターンに直接渡されます。

ただし、ここではいくつかの最適化を実行できます。まず、単語リストに次の項目のみが含まれていることを確認できます。ユニーク性格:

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

また、次の単語だけが一致することを確認することもできます。最初固定正規表現で単語を書き換え(およびドロップ)して、2番目のファイル-Fから列を削除します。

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

このsedコマンドは^各行の先頭に挿入されるため、bee文字列の代わりに正規表現を取得します^bee


または、1つのawkプログラムを使用してすべての操作を実行できます。

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

これは、最初のファイルの最初のタブで区切られた列をキーとして配列として読み取った後、2番目のファイルでそのキーに基づくwords単語を識別します。 2番目のファイルの単語がキーとして表示される場合は、2番目のファイルの行を印刷します。


出力順序を気にしない場合は、次を使用することもできます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

関連情報