テーブルファイルがあります
2e95d7582c53583fa8afb54e0fe7a2597c92cbba 1461065389 52880 temp/hello/file.txt
46c897a7aa8a641f46080b3431860bd0cd4a8f05 1461066221 207 temp/Another file.txt
83c8ce6b163ec1c615617fa0dbde9e928bc3daf4 1461056193 86112 Pictures/a photo.jpg
...
つまり、各行には40文字の16進数字が含まれ、その後にスペース、整数、スペース、整数、スペース、スペースを含めることができるファイルパスが続きます。すべての道路はユニークです。
Bashスクリプトでは、私の変数は最初の16進文字列とスペース(最初の41文字)だけを除いてファイルの行と同じ形式を持ちます。たとえば、次のようになります。
myvar="1461066221 207 temp/Another file.txt"
私の目標は探すことです。これファイルの一致行myvar
正確に最初の41文字は無視されます。そのような一致が見つかったら、変数をline
ファイルの完全な行に設定したいと思います。上記の例では、line
次のように設定されています。
46c897a7aa8a641f46080b3431860bd0cd4a8f05 1461066221 207 temp/Another file.txt
一致するものがない場合は、空のline
文字列に設定するか、まったく設定しないでください。
私の解決策は次のとおりです(filelist
ファイル名)。
line=$(grep --color=never -E "^.{41}$myvar$" $filelist)
1つの問題は、拡張に特別な意味を持つ、Evenなどの$myvar
特殊記号を含めることができることです。公演したい.
+
^
$
grep
grep
精密myvar
1行の最初の41文字を除くすべての文字と一致します。
答え1
Perlが救出に来る!
perl -ne 'BEGIN { $search = shift }
print if /^.{41}\Q$search\E$/;
' -- "$myvar" "$filelist"
-n
ファイルを1行ずつ読みます。- BEGINブロックは、Perl変数$ searchの最初の引数で$ myvarを検索します。
\Q...\E
内部部品の引用(参照)参照要素)。これは変数に含めることができるすべての特殊文字を処理します。シェル変数を二重引用符で囲むことを忘れないでください!
答え2
export myvar
awk 'substr($0, 42) == ENVIRON["myvar"]' < "$filelist"
答え3
これは別のアプローチです。まず 'line' を空白に設定し、次の 3 つのフィールドに一致する項目を見つけたら 'myvar' を設定します。
line=
while IFS=' ' read -r hex int1 int2 rest
do
if [[ "$myvar" = "$int1 $int2 $rest" ]]
then
line="$hex $int1 $int2 $rest"
fi
done < filelist
bashのmapfile
組み込みと2番目の一時的な連想配列を使用する別のアプローチは次のとおりです。
mapfile -t < filelist # sets MAPFILE array
declare -A temparray
shopt -s extglob
for val in "${MAPFILE[@]}"
do
short="${val##*([^ ]) }"
temparray[$short]="$val"
done
line=${m[$myvar]}
unset -v MAPFILE temparray val short
これは、ファイルをインデックス配列MAPFILEに入れてから繰り返します。このループは、「short」変数を行の「サフィックス」部分に設定します。 「ゼロ個以上の非空白の後に空白が続く」パターンに一致する先行値を削除し、「$」shortの連想配列値を設定します。 「を整数行(「$ val」)に置き換えます。これが*
必要ですshopt -s extglob
。次に、lineを結果の値に設定します(またはその値が配列にない場合、bashはnull / nullを返します)。