make
Bashスクリプトを使用して単純なLinuxコマンドを作成しようとしています。これが私がこれまでに書いた内容です:
#!/usr/bin/env bash
function make_cmd()
{
read target colon sources
for src in $sources; do
if [ $src -nt $target ]; then
while read cmd && [[ $(echo "$cmd" | grep "$(printf '\t')"*) ]]; do
echo "executing $cmd";
eval ${cmd#$(printf '\t')};
done
break;
fi
done
}
入力形式は次のとおりです。
target.file : source.file
[tab]command
たとえば、
target.txt : source.txt
ls
cd
スクリプトは正常に実行されますが、タブで始まるコマンドは見つかりません。常に実行されます。たとえば、この入力のコマンドは引き続き実行されます。
target.txt : source.txt
ls
cd
この問題をどのように解決できますか?
答え1
組み込みコマンドは、デフォルトでスペース、タブ、および改行を含むread
値を使用して単語を分割します。IFS
したがって、入力を受け取るとread
タブが削除されます。
関数は次から始まります。
IFS_SAVE="$IFS"
IFS=' '
これで、空白のみの単語を区別できます。関数が終了したら、IFSを元の値に復元します。
IFS="$IFS_SAVE"
バックスラッシュでエスケープすると、リテラルタブを使用できます。また、grep
マッチングタブを使用せずに可能な限り組み込み機能を使用する方が高速です。私の機能バージョンは次のとおりです。
function make_cmd()
{
SAVE_IFS="$IFS"
IFS=' '
read target colon sources
for src in $sources; do
if [ $src -nt $target ]; then
while read cmd; do
case "$cmd" in
$'\t'*) echo "executing $cmd"
eval ${cmd# }
;;
*) ;;
esac
done
break;
fi
done
IFS="$SAVE_IFS"
}
リテラルタブを置き換えました$'\t'
(ヒントをくれたKusalalanandaに感謝します)。
#
変数の置換後にリテラルタブを挿入します。しかし、printf
使用する方が読みやすくなります。