17列と100万行のcsvファイルがあります。 16番目の列で特定の文字列を検索し、その文字列のすべてのインスタンスを別の文字列に置き換えます。プログラムの残りの部分ではbashスクリプトを使用しているので、Python search&replaceの代わりにawkを使用することを考えました。現在のOSはRhel6です。
以下は、私のデータのサンプル出力です。
SUBSCRIBER_ID|ACCOUNT_CATEGORY|ACCOUNT_ACTIVATION_DATE|PACKAGE_NAME|PACKAGE_TYPE|DURATION|ACTIVE_DATE|INACTIVE_DATE|STB_NO|PRIMARY_SECONDARY|MODEL_TYPE|VC_NO|MULTIROOM|STB_TYPE|IPKG|SERVICE_STATE|CURRENT_STATUS
1001098068|ResidentialRegular|01/20/2007|Annual package 199 May17 pack|Basic Package|Annual|08/28/2017||027445053518|Primary|Pace - 31|000223871682|Yes|AMP|Package 199 pack|Market1|Active
1001098068|ResidentialRegular|01/20/2007|Annual Pack|Premium Package|Annual|08/28/2017||027445053518|Primary|Pace - 31|000223871682|Yes|AMP|English Movies pack|Market1|Active
1001098068|ResidentialRegular|01/20/2007|Annual SingleUnit Jun17 Pack|Secondary Pack|Annual|08/28/2017||032089364015|Secondary|Kaon|000017213968|Yes|AMP|SingleUnit|Market2|Active
これの16番目の列はMarketです。ここでMarket1
からMarketPrime
へ。ファイルの名前はmarketinfo_2018-06-26.csv
私は次のコードを試しました:
awk -F '| +' '{gsub("Market1","MarketPrime",$16); print}' OFS="|" marketinfo_2018-06-26.csv > marketinfo_2018-06-26.csv
これは出力なしで実行されますが、文字列Market1
はまだ残っています。
awk -F '|' -v OFS='|' '$16 == "Market1" { $16 = "MarketPrime" }1' file.csv >new-file.csv
コードの唯一の実際の問題は、入力ファイルの区切り文字を|
だけでなくスペースにも設定することです。これにより、データ内のスペース区切りとしてスペースがカウントされ、正しいフィールド番号が何であるかを理解するのは非常に困難になります(一部のフィールドには可変数のスペースが含まれているため)。
また、読み取りに使用するのと同じファイル名にリダイレクトすることもできません。そうすると、シェルは最初に出力ファイルを切り捨て(空に)し、awk
プログラムには読み取るデータがありません。
コードは正規表現の置換を行います。これは問題ありませんが、16番目のフィールドがMarket12
またはTheMarket1
のようなものである場合、アンカーポイントがないために置換がトリガーされることに注意する必要があります。置換する式として^Market1$
を使用するか、文字列比較を使用する方が安全です。
上記のawk
コマンドは、フィールド区切り文字として|
のみを使用し、16番目のフィールドとの文字列比較を行います。そのフィールドがMarket1
の場合、MarketPrime
に設定されます。
awk
コードの末尾の末尾の1
により、すべてのレコード(変更されているかどうかにかかわらず)が印刷されます。
問題は、入力フィールドのセパレータにあります。
複数のフィールド区切り記号を使用する必要があるため(これは必須ではありません)、以下に示すように、各行のフィールド数は異なります。
$ awk -F '[| +]' '{print NF}' test.csv
17
26
23
21
iFSとして|
のみを使用する場合、コードは機能します。以下に示すように、各行には17個のフィールドがあるため。
awk -F "|" '{print NF}' test.csv
17
17
17
17
ソリューション1:複数のIFSを使用。
awk -F '[| +]' '{gsub("Market1","MarketPrime",$(NF-1)); print}' OFS="|" test.csv
SUBSCRIBER_ID|ACCOUNT_CATEGORY|ACCOUNT_ACTIVATION_DATE|PACKAGE_NAME|PACKAGE_TYPE|DURATION|ACTIVE_DATE|INACTIVE_DATE|STB_NO|PRIMARY_SECONDARY|MODEL_TYPE|VC_NO|MULTIROOM|STB_TYPE|IPKG|SERVICE_STATE|CURRENT_STATUS
1001098068|ResidentialRegular|01/20/2007|Annual|package|199|May17|pack|Basic|Package|Annual|08/28/2017||027445053518|Primary|Pace|-|31|000223871682|Yes|AMP|Package|199|pack|MarketPrime|Active
1001098068|ResidentialRegular|01/20/2007|Annual|Pack|Premium|Package|Annual|08/28/2017||027445053518|Primary|Pace|-|31|000223871682|Yes|AMP|English|Movies|pack|MarketPrime|Active
1001098068|ResidentialRegular|01/20/2007|Annual SingleUnit Jun17 Pack|Secondary Pack|Annual|08/28/2017||032089364015|Secondary|Kaon|000017213968|Yes|AMP|SingleUnit|Market2|Active
ソリューション2:固定フィールド16
awk -F '|' '{gsub("Market1","MarketPrime",$16); print}' OFS="|" test.csv
SUBSCRIBER_ID|ACCOUNT_CATEGORY|ACCOUNT_ACTIVATION_DATE|PACKAGE_NAME|PACKAGE_TYPE|DURATION|ACTIVE_DATE|INACTIVE_DATE|STB_NO|PRIMARY_SECONDARY|MODEL_TYPE|VC_NO|MULTIROOM|STB_TYPE|IPKG|SERVICE_STATE|CURRENT_STATUS
1001098068|ResidentialRegular|01/20/2007|Annual package 199 May17 pack|Basic Package|Annual|08/28/2017||027445053518|Primary|Pace - 31|000223871682|Yes|AMP|Package 199 pack|MarketPrime|Active
1001098068|ResidentialRegular|01/20/2007|Annual Pack|Premium Package|Annual|08/28/2017||027445053518|Primary|Pace - 31|000223871682|Yes|AMP|English Movies pack|MarketPrime|Active
1001098068|ResidentialRegular|01/20/2007|Annual SingleUnit Jun17 Pack|Secondary Pack|Annual|08/28/2017||032089364015|Secondary|Kaon|000017213968|Yes|AMP|SingleUnit|Market2|Active
同様の問題に直面する可能性がある他の人のために明確にするために:
これらの答えは両方とも、このシナリオで機能しました。
クサラナンダの答え:
awk -F '|' -v OFS='|' '$16 == "Market1" { $16 = "MarketPrime" }1' file.csv >new-file.csv
クサラナンダの答えに基づく私の修正された答え:
awk -F '|' '{gsub("Market1","MarketPrime",$16); print}' OFS="|" marketinfo_2018-06-26.csv > marketinfo_2018-06-26.csv