文字列をコマンドの最後に移動

文字列をコマンドの最後に移動

再利用したい注文を作成しましたが、関数として保存するには一時的な修正に脆弱です。これらのコマンドには、内部に深く埋め込まれたファイル名など、いくつかの主要な変数コンポーネントが含まれることがよくあります。このコンポーネントをコマンドの最後に移動したいと思います。

たとえば、私の最新の桟橋は、INSERTdiffファイル内のすべての新しいステートメントのテーブル定義を印刷します。

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。これを$PATHexport 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 readKusalananda が提案した構文に置き換えました。したがって、最終的な構文は次のようになります。

_() { 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

この方法は、必要なコマンドのどの部分でも調整できる機能を維持しますが、コマンド自体から引用符をエスケープすることなく、パラメータ(この場合はファイル名)を簡単に変更できます。

関連情報