array [1]は、30,000行のCSVから抽出された文字列です。例:
samsung black 2014
この行を配列(arrayItems)に含まれる値の1つと一致させる必要があります。
arrayItemsには221個の値が含まれています。例:
apple
sony
samsung
実際のスクリプト:
while IFS=$';' read -r -a array
do
mapfile -t arrayItems < $itemsFile
## now loop through the above array
for itemToFind in "${arrayItems[@]}"
do
itemFound=""
itemFound="$(echo ${array[1]} | grep -o '^$itemToFind')"
if [ -n "$itemFound" ]
then
echo $itemFound
# so end to search in case the item is found
break
fi
done
# here I do something with ${array[2]}, ${array[4]} line by line and so on,
# so I can't match the whole file $file_in at once but online line by line.
done < $file_in
問題はgrepが一致しないことです。
しかし、$ itemToFindを次のようにハードコーディングしようとするとうまくいきます。
itemFound="$(echo ${array[1]} | grep -o '^samsung')"
もう一つの問題は... $ file_inが30,000行のCSVの場合、どうすればより速く処理できますか?
答え1
ファイルモードオプション(-f)でgrepを使用できます。
例:
$ echo -e "apple\nsony\nsamsung" > file_pattern
$ grep -f file_pattern your.csv
編集:新しい制限に応じて:
sed 's/^/\^/g' $itemsFile > /tmp/pattern_file
while IFS=$';' read -r -a array
do
echo ${array[1]} | grep -q -f /tmp/pattern_file.txt
if [ $? -eq 0 ]; then
# here I do something with ${array[2]}, ${array[4]} line by line and so on,
# so I can't match the whole file $file_in at once but online line by line.
fi
done < $file_in
答え2
スクリプトには2つのエラーがあります。
$itemToFind
grepは一重引用符の間に文字列を入れるため、文字列の一致を試みます'
。代わりに二重引用符を使用してください。インデックス1の配列を使用しており、
help read
0から始まるように指示しています。
これは以下を提供する必要があります。
while IFS=$';' read -r -a array
do
mapfile -t arrayItems < $itemsFile
## now loop through the above array
for itemToFind in "${arrayItems[@]}"
do
itemFound=""
itemFound=$(echo ${array[0]} | grep -o "$itemToFind")
if [ -n "$itemFound" ]
then
echo $itemFound
# so end to search in case the item is found
break
fi
done
done < $file_in
編集する:
より速くしたい場合は、拡張正規表現を使用できます。
grep -E 'apple|sony|samsung' $file_in
ブランドのみを表示したい場合:
grep -E 'apple|sony|samsung' $file_in | awk '{print $1}'