再利用したい注文を作成しましたが、関数として保存するには一時的な修正に脆弱です。これらのコマンドには、内部に深く埋め込まれたファイル名など、いくつかの主要な変数コンポーネントが含まれることがよくあります。このコンポーネントをコマンドの最後に移動したいと思います。
たとえば、私の最新の桟橋は、INSERT
diffファイル内のすべての新しいステートメントのテーブル定義を印刷します。
for T in $(grep -oP "(?<=^\+INSERT INTO \`)[\w-]+(?=\`)" foo.diff | sort -u) ; do docker-compose exec mysql mysqldump --no-data some_database $T | grep -P "^\s*\`|^CREATE|^\) |^\s*CONSTRAINT" | sed "s/ COMMENT .*,$/,/" | sed "s/CONSTRAINT \`\w*\` //" | sed "s/^) ENGINE.*;/);/" ; done
読みやすくするために書式設定:
for T in $(grep -oP "(?<=^\+INSERT INTO \`)[\w-]+(?=\`)" foo.diff | sort -u)
do
docker-compose exec mysql mysqldump --no-data some_database $T
| grep -P "^\s*\`|^CREATE|^\) |^\s*CONSTRAINT"
| sed "s/ COMMENT .*,$/,/"
| sed "s/CONSTRAINT \`\w*\` //"
| sed "s/^) ENGINE.*;/);/"
done
私は後でというファイルではなく、ファイルに対してこのコマンドを再利用したいので、コマンドfoo.diff
はファイル名で終わりたいと思います。私の最初の傾向は、すべてを関数で囲み、ファイル名を$ 1パラメータとして渡すことです。
ただし、実行時にさらに調整する可能性が高くなります。ここにsedを追加してください。たぶんそこに少しぎこちないかもしれません。したがってCtrl-P
、再実行しても、コマンド全体がCLIにあることを望みます。だから変数を使うことにしました。
$ FILENAME=diff-03-04.sql
今日は注文ごとに同じファイルを使用するので、この特定の例に適していますが、コマンドの最後を調整できる他の例もあります。だからこれ:
$ for Q in $(foo Torvalds bar) ; do baz $Q ; done
次のようなものですが、必ずしも同じではありません。
$ for Q in $(foo SOME_MAGIC_HERE bar) ; do baz $Q ; done < Torvalds
答え1
スクリプトや関数の力を誤って理解しているようです。個人的には、スクリプトが独立していて、どのインタラクティブシェルを使用しても使用できるため、スクリプトを好みます。しかし、関数は同じことをすることができます。私にとって、システム全体のスクリプトはに入り、/usr/local/bin
個人(ジャンク)スクリプトはに入ります~/bin
。どちらも私の中にいます$PATH
。
ディレクトリを作成します~/bin
。これを$PATH
(export PATH="$PATH:$HOME/bin"
)に追加してください。これで、このディレクトリにある実行可能スクリプトを新しいコマンドとして使用できるようになりました。
あなたの例を見てみましょう。使用時にファイル名を選択したいので、これをスクリプトの最初の引数にしましょう。
ファイルの作成~/bin/tables
:
#!/bin/bash
file=$1
for T in $(grep -oP "(?<=^\+INSERT INTO \`)[\w-]+(?=\`)" "$file" | sort -u)
do
docker-compose exec mysql mysqldump --no-data some_database "$T"
| grep -P "^\s*\`|^CREATE|^\) |^\s*CONSTRAINT"
| sed "s/ COMMENT .*,$/,/"
| sed "s/CONSTRAINT \`\w*\` //"
| sed "s/^) ENGINE.*;/);/"
done
スクリプトを実行可能にすると、chmod a+x ~/bin/tables
新しいコマンドが生成されます。
tables foo.diff
tables another.diff
答え2
ここにいるすべての人は、他の回答やコメントから素晴らしいアドバイスを提供しました。私が見つけた最良の方法は、コマンドを関数にラップし、その関数を単一のコマンドとして実行することです。
$ _() { echo $1; } && _ beer
beer
$
また、for T in $()
構文をcmd | while read
Kusalananda が提案した構文に置き換えました。したがって、最終的な構文は次のようになります。
_() { grep -oP "(?<=^\+INSERT INTO \`)[\w-]+(?=\`)" $1 | sort -u | while read -r T ; do docker-compose exec mysql mysqldump --no-data some_database $T | grep -P "^\s*\`|^CREATE|^\) |^\s*CONSTRAINT" | sed "s/ COMMENT .*,$/,/" | sed "s/CONSTRAINT \`\w*\` //" | sed "s/^) ENGINE.*;/);/" ; done } && _ foo.diff
読みやすくするために書式設定:
_() {
grep -oP "(?<=^\+INSERT INTO \`)[\w-]+(?=\`)" $1
| sort -u
| while read -r T ;
do
docker-compose exec mysql mysqldump --no-data some_database $T
| grep -P "^\s*\`|^CREATE|^\) |^\s*CONSTRAINT"
| sed "s/ COMMENT .*,$/,/"
| sed "s/CONSTRAINT \`\w*\` //"
| sed "s/^) ENGINE.*;/);/"
done
}
&& _ foo.diff
この方法は、必要なコマンドのどの部分でも調整できる機能を維持しますが、コマンド自体から引用符をエスケープすることなく、パラメータ(この場合はファイル名)を簡単に変更できます。