シェルでリストの操作を実行する

シェルでリストの操作を実行する

削除したいパッケージのリストがあります。アンインストーラはpkg_deinstallパッケージリストをアンインストールパラメータとして使用しません。 foreachループのようなリストからどのようにアンロードしますか?

[root@fbsd01 /usr/ports/editors/vim]# pkg_info | grep proto| sed 's/\([a-z0-9]*\).*/\1/'
bigreqsproto
compositeproto
damageproto
fixesproto
fontsproto
inputproto
kbproto
randrproto
renderproto
xcb
xcmiscproto
xextproto
xf86bigfontproto
xineramaproto

同様のコマンドが機能すると思いますが、ストリームの代わりにパラメータとしてリストを渡す必要があります。pkg_info | grep proto| sed 's/\([a-z0-9]*\).*/\1/' | head -n 1 pkg_deinstall

どのプログラムと構文を使用すべきかについての手がかりを提供してください。個人差があるため、正確な回答ができない場合があります。私の問題が複雑すぎる場合は、誰かがlsディレクトリ内のファイルに対して何をするかを教えてください。

答え1

最も基本的な「foreach」の場合は、xargsいくつかのパラメータを読み取り、それを別のコマンドラインに追加します。たとえば、次のことを試すことができます。

> cut -d: -f1 /etc/passwd | xargs -n1 echo user:

-d'\n'ユーザー名にスペース文字を含めることができる場合は、パラメータを渡す必要があります。xargs同じコマンドに1つの引数をすべて追加するには、次のようにします。

> cut -d: -f1 /etc/passwd | xargs echo users:

より一般的なループの場合は、次のものを使用できます。

> cut -d: -f1 /etc/passwd | while read i; do echo $i; done

今回は、$i1つ以上のコマンドシーケンスのどこにでも配置できます。入力は一度に1行ずつ読み取られ、変数に保存されますi。 ²行を分割して複数の変数に保存することもできます。

> cut -d: -f1,6 /etc/passwd --output-delimiter=' ' | \
  while read i j; do echo home directory of user $i is $j; done

生ファイル名を繰り返す場合は、次の方が良いです(コメントを参照)。

> for i in *.txt; do echo file: $i; done


1. より正確には、システムが許可する金額です。 2.変数
に応じてIFS

答え2

出力ストリームをパラメータリストに変換する2つの主な方法があります。これを行うための簡単な(時には汚れた)方法はを使用することですxargs。デフォルトでは、標準入力ストリームを受け入れ、各入力行を別々の引数として使用してコマンドを実行します。スペースやその他の文字は引数として渡されると簡単に誤解される可能性があるため、常に入力形式に注意する必要があります。ただし、パッケージ名は比較的安全です。これには、シェルワイルドカードや改行文字などの奇妙な文字を含めないでください。したがって、コマンドは次のようになります。[3]

$ pkg_info | grep proto | sed 's/\([a-z0-9]*\).*/\1/' | xargs pkg_deinstall -n

一般的な状況は、実際に処理される各行に対してコマンドを一度実行する必要があることです。この場合、-n引数が便利です。-n1一度に 1 つずつ実行することも、-n1010 つずつ一括実行することもできます。

$ [pipline] | xargs -n1 pkg_deinstall -n

それでは、自動的に生成されたパラメータの後に別のパラメータを追加する必要があるとします。この場合、-Iを使用して自動生成された引数を置き換える文字列を指定できます。また、必要に応じて引数参照などの操作を実行することもできます。その後、パラメータが配置される場所の形式を次のように指定できます。[1][2]

$ [pipline] | xargs -n1 -I{} pkg_deinstall -n "{}" --trailing-argument

より多くの制御が必要な場合、または各入力行に対して複数のコマンドを実行するには、次のオプションは次のループを使用することです。

$ [pipline] | while read line; do
      echo "Uninstalling $line..."
      pkg_deinstall -n "$line"
  done

pkg_deinstall一致するglobの一部として式を自動的に使用するため、アンロードするために渡す内容に注意してください。一部のシステムコンポーネントのデフォルト名を渡すと、そのコンポーネントだけでなく、名前が似ているか、それに依存するすべてのコンポーネントが削除されます。これは災害になる可能性があるため、必ずキットを慎重に確認してください。実際に[3]を実行したり、各ステップを対話的に実行したりすることなく実行されるタスクを-n示すためにテスト実行を実行するために使用できます。-i

{}[1] findや他の同様のexec関数はこの型を使用しているため、forを使用していますが、任意の一意の文字列を使用できます。
[2]pkg_deinstallコマンドにはパターンの後に引数がないので、これは単なる例です! [3]コードをコピーして貼り付けると、実際にはテスト実行のみを表示する以外は何もしないようにすべての例に
追加しました。-n

答え3

他の答えを無視しないでください。これは別のアプローチです。

for pkg in $( pkg_info | grep proto| sed 's/\([a-z0-9]*\).*/\1/' ) ; do
    pkg_deinstall $pkg
done

例文では、引用文は悪夢なので、個人的に引用| while read foo ...文をより頻繁に使用する傾向があります。

関連情報