awk内で、入力フィールドの値に基づいて別のディレクトリに新しいファイルを作成します。

awk内で、入力フィールドの値に基づいて別のディレクトリに新しいファイルを作成します。

awkを使用しようとしています。

    datetime=`date +\%Y\%m\%d`
    logdatetime=`date +\%Y\%m\%d`
    foldermonth=`date +\%B_\%Y`
    folderday=`date +\%d`
    inputdir="~/sboper/Standalone/fsplit/GLMS"
    outputdir="~/sboper/StandAlone/input/$foldermonth"
  outputdirday="~/sboper/StandAlone/input/$foldermonth/GLMS_Daily/$folderday"

    awk -v outdir=$outputdirday 'BEGIN{ FS = "~" } ;{if( $12 == "A" ) filename="outdir/Customer_Create_Records.dat" ; print >> filename;close(filename)}' $inputdir/$sourcefile

    awk -v outdir=$outputdirday 'BEGIN{ FS = "~" } ;{if( $12 == "M" ) filename="outdir/Customer_Modify_Records.dat" ; print >> filename;close(filename)}' $inputdir/$sourcefile

ただし、変数はoutdir=$outputdirday私の出力ディレクトリパスの値には拡張されません。

awk変数を宣言しましたが、awkスクリプトでシェル変数を使用しませんでした。しかし、まだエラーが発生しますcannot open Customer_Create_Records.dat

私のスクリプトに何の問題がありますか? "outdir"の代わりにフルパスをコピーすると、新しいファイルが作成され、レコードが移動されますが、変数に使用されると正しく機能しません。 awkを使って、どのディレクトリに新しいファイルを作成できますか?

答え1

うわー。どこから始めるべきですか?

  • デバッグする方法を学ぶ必要があります。  Bashスクリプトをデバッグする方法は? このトピックの高い評価を受けたStack Exchangeの参考資料で、最も活動的なメンバーの一部が貢献しました。このサイトで追加情報を見つけることができ、ウェブ上でより多くの情報を見つけることができます。例えば、
    • 単純化する。
      • folderday、割り当てを削除しfoldermonth て定数値で設定します。`date …`outputdirday
      • 混乱するほど類似した変数名を避けてください。たとえば、とoutdir同じですが、他のものです。outputdirdayoutputdir
      • datetime未使用、logdatetimeおよびスクリプトも削除してください。outputdir
      • 重複を削除します。表示される2つのコマンドは、awkマイナーな違いを除いて同じです。そのうちの1つは動作し、1つは失敗しますか?彼らは別の方法で失敗するでしょうか?私はそうは思わない。それでは、両方を見ないようにしてください。
      • 実際に使用しない限り、長い8段階のパス名(例~/sboper/StandAlone/input/$foldermonth/GLMS_Daily/$folderday/Customer_Create_Records.dat:)を使用しないでください。本物必要。
    • デモンストレーション目的(つまり、他人に問題をデモンストレーションするとき)に、出力ディレクトリの命名などの混同される命名規則を避けてください…/input/…
    • プレゼンテーション目的で画面より広い行を使用しないでください。したがって、内容全体を読むにはスクロールする必要があります。ほとんどのシステムには、コマンドとプログラムを複数行に分割する方法があります。
    • ディレクトリに実際に2つのディレクトリ(1つは呼び出され、もう1つは呼び出されます)がありますかStandaloneStandAlone~/sboper
    • 最終結果が目的の結果でない場合は、プロセスの途中で何が起こったかを確認してください。中間値を表示します。例えば、
      • outputdirday。スクリプトを実行してecho "$outputdirday"以前に実行すると、awk次の結果が表示されます。
        ~/sboper/StandAlone/input/June_2016/GLMS_Daily/08
        つまり、~引用符で囲まれているため、私のホームディレクトリには展開されません。課題を次のように変更する必要がありました。
        outputdirday="$HOME/sboper/StandAlone/input/$foldermonth/GLMS_Daily/$folderday"
        動作させる。
      • outdir。正しく設定されていないというのに、印刷してみましたか?これにより、私が得たのと同じ値が得られますoutputdirday
      • filename。  これ問題(部分)については、以下を参照してください。
  • 助けを求めるときにすべきこと
    • 上記のように問題を単純化します。
    • コマンドが実行する必要がある作業について説明してください。
    • 入力ファイルの外観を表示します。
    • 予想される出力がどのように見えるかを示してください。
    • 使用しているソフトウェアのバージョンを確認してください。私はあなたのスクリプトにどのような問題があるかを理解していると思いますが、あなたのエラーを正確に再現することはできません(したがって、別のバージョンを実行しているようですawk)。おそらく本物重要ですが、どのオペレーティングシステムを使用しているのかは明らかではありませんでした。


これは重要な部分です:

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

  • 上記のように、スクリプトの基本作業ブロックをより短い行に分割した場合は、awkその内容が次のようになることに気づいたはずです。
    {
          if ( $12 == "A" )
                ファイル名="outdir/Customer_Create_Records.dat"
          印刷>>ファイル名
          閉じる(ファイル名)
    }
    〜のようにマイケル・ウェルズで指摘する彼の答え、このグループfilename ホームフレーズと入力してすべて行を入力してくださいfilename 無条件。彼が提案したように、次のことを行う必要があります。
    {
          if($12=="A"){
                ファイル名="outdir/Customer_Create_Records.dat"
                印刷>>ファイル名
                閉じる(ファイル名)
          }
    }
  • filename上記のように値を設定して印刷すると、次の値が表示されます。
    outdir/Customer_Create_Records.dat
    "outdir"(引用符内の)意味 はひも outdir、代わりに変数をoutdir実行する必要があります。
    ファイル名 = outdir "/Customer_Create_Records.dat"

↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

ほとんど重要なもの:

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

  • 妥当な理由がなく、実行している操作がわからない限り、必ずシェル変数参照(例、、"$outputdirday"および"$inputdir")を引用する必要があります。"$sourcefile"これは問題の原因ではないようですが、最終的には問題を引き起こします。
  • 明確にするために、次のよう`…`に変更したい場合があります。$(…)これこれこれ

↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

  • 妥当な理由がない限り、常にシェル変数参照を引用する必要がありますが、これはバックスラッシュには適用されません。正当な場合にのみ使用してください。たとえば、date +%Y%m%d背中date +%B_%Yはうまく機能します。
  • awk以前に提案したように、実行中の操作に対して2回呼び出す必要はありません。あなたはすべてを達成することができます

    awk -v outdir="$outputdirday" '
        BEGIN { FS = "~"
                filenameA = outdir "/Customer_Create_Records.dat"
                filenameM = outdir "/Customer_Modify_Records.dat"
              }
              {
                if ($12 == "A") print >> filenameA
                if ($12 == "M") print >> filenameM
              }
        ' "$inputdir/$sourcefile"
    

    または

    awk -v outdir="$outputdirday" '
        BEGIN { FS = "~"
                filenameA = outdir "/Customer_Create_Records.dat"
                filenameM = outdir "/Customer_Modify_Records.dat"
              }
        $12 == "A" { print >> filenameA}
        $12 == "M" { print >> filenameM}
        '    "$inputdir/$sourcefile"
    

    私が知る限り、closeこれらのファイルはまったく必要ありません。ファイルは通常、プログラムが終了すると自動的に閉じます。

答え2

あなたの質問は明確ではありませんが、次のことを望むかもしれません。

if( $12 == "A" ) {
    filename="outdir/Customer_Create_Records.dat" ;
    print >> filename;close(filename)
}

中括弧がない場合、条件文の「then」句は最初のセミコロンで終わります。したがって、出力ファイルの名前を定義する前に、出力ファイルに行を書き込もうとすることができます。

答え3

問題は、awk構文とawkに提供する入力ファイルにあります。 "$inputdir/$sourcefile" - 単一のファイル名には拡張されません。

回答を投稿した皆さんに感謝します。エラーを理解するのに役立ちました。生成されたコードは次のとおりです(これはより大きなスクリプトの断片なので、私が宣言するすべての変数はこの断片にのみ関連していない可能性があります)。

    timestamp=`date +\%Y\%m\%d\%H\%M\%S`
    logfile=/udd001/sboper/CMStandAlone/input/logs/SBSA_GLMS_CUST_$timestamp.log
    datetime=`date +\%Y\%m\%d`
    logdatetime=`date +\%Y\%m\%d`
    foldermonth=`date +\%B_\%Y`
    folderday=`date +\%d`
    inputdir="/udd001/sboper/CMStandalone/fsplit/GLMS"
    outputdir="/udd001/sboper/CMStandAlone/input/$foldermonth"
    outputdirday="/udd001/sboper/CMStandAlone/input/$foldermonth/GLMS_Daily/$folderday"
    inputfile=$( ls -1 /udd001/sboper/CMStandalone/fsplit/GLMS/GCP1_cdf_001_$datetime*.txt )
    sourcefile=`basename $inputfile`

    if [ ! -d "$outputdirday" ]; then
            mkdir -p "$outputdirday"
            fi
                    if [ -f "$inputdir/$sourcefile" ]
                    then
                    cp "$inputdir/$sourcefile" "$outputdirday"

                    echo "output directory : $outputdirday"
                     awk -v outdir="$outputdirday" '
                        BEGIN { FS = "~"
                        filenameA = outdir"/SBSA_Amdocs_Customer_Create_Records.dat"
                        filenameM = outdir"/SBSA_Amdocs_Customer_Modify_Records.dat"
                        }
                        $12 == "A" { print >> filenameA}
                        $12 == "M" { print >> filenameM}
                        '    "$inputdir/$sourcefile

        fi        

関連情報