ファイルの各行から最初の単語を取得する切り取りコマンドがあります。その後、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
静かにするように指示し、一致するものがあるかどうか$?
尋ねることができます。0
1
答え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
その後、最初のファイルから単語が抽出され、grep
2番目のファイルと一致するために使用されるパターンに直接渡されます。
ただし、ここではいくつかの最適化を実行できます。まず、単語リストに次の項目のみが含まれていることを確認できます。ユニーク性格:
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
(例:bee
in 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