ファイルの複数の列の値を検索して一致させるには、awkコマンドをどのように変更しますか?

ファイルの複数の列の値を検索して一致させるには、awkコマンドをどのように変更しますか?

次のスクリプトが保存されておりbin、定義された変数に基づいて出力を取得するために使用されます。現在、スクリプトは列1に対して実行されており、出力を提供しています。列1または列2と一致するときに出力を提供するようにこのスクリプトをどのように更新できますか?

cat ~/bin/POUT

#!/bin/bash

exec awk -v arg=${1:?} '$1==arg' "${@:2}" inputfile

入力ファイル -:

 DEV       RETAIL          RETAILDEVNode  
TEST      RETAILTEST       RETAILTESTNode 
TEST       AUDIT            AUDITTESTNode
QA         AUDITQA         AUDITQANode
PROD       SALE            SALEPRODNode
QA         SALEQA           SALETESTNode
QA        FINANCE         FINANCEQANode
PROD      FINANCE         FINANCEPRODNode

現在予想される結果を得ています -

$ POUT QA
QA         AUDITQA         AUDITQANode
QA         SALEQA           SALETESTNode
QA        FINANCE         FINANCEQANode

また、次のような出力が必要です(列2でも検索)。

$ POUT AUDITQA
QA         AUDITQA         AUDITQANode

Want output like this also (put any matching value and search in column 2 aslo) ---

$ POUT DITQ 
QA         AUDITQA         AUDITQANode

したがって、変数に入力が何であれ、列1と列2を検索して出力を提供する必要があります。

答え1

#!/bin/bash
arg="${1:?}"    # Capture argument value or fail
shift

awk -v arg="${arg//\\/\\\\}" 'index($1, arg) || index($2, arg)' "$@" inputfile

シェル変数を使用するときは常に二重引用符を使用してください。 (例外が発生する理由を理解するまでこれは本当です。それまでは常に二重引用符を使用してください。)

$argシェル変数は、バックスラッシュ処理をキャンセルするためにawk変数をランダムに変数に割り当てます。argawk

残りのコマンドライン引数を渡す理由は理解できません。awk そしてinputfile継続的なソースとして提供されます。それでも意図した場合に備えて保管しました。

答え2

可能:

#! /bin/sh -
export ARG="${1?}"
shift
exec awk '
  BEGIN{
    field = 1
    arg = ENVIRON["ARG"] ""
  }
  $field == arg' "$@" inputfile

その後、これを呼び出して、CLI以前のバージョンとの互換性を維持しながら2番目のフィールドをPOUT AUDITQA field=2確認できます。AUDITQA

いくつかの注意:

  • bashまたはshで引用符を拡張することを忘れた場合、-v arg=${1?}これはSplit + globの影響を受けます。これは、任意のコマンド実行の脆弱性を引き起こすので、非常に悪いです。これは実際に与えられた例の一つです。bash / POSIXシェルで変数を引用することを忘れてしまうセキュリティリスク
  • -v任意のテキストを渡すためにマングルバックスラッシュを使用することはできません-v。したがって、ENVIRON上記の方法を使用しても問題はありません。
  • awk引数は変数の代入として扱われるため、foo=bar.txtファイル名に文字が含まれている場合。代わり=に転送する必要があります。./foo=bar.txtfoo=bar.txt
  • $fieldおよびENVION["var"]/または-v数値として見える渡された変数は、数値文字列として扱われ、==最終的に文字列比較の代わりに数値比較を実行することができます。常に文字列として処理されるように接続するため、たとえば""引数を使用して呼び出すと、10.0、010、または1e1と一致しません。ENVIRON["ARG"]10

関連情報