awk CSV 파일의 특정 열에서 문자열 검색 및 바꾸기

awk CSV 파일의 특정 열에서 문자열 검색 및 바꾸기

17개의 열과 100만 개의 행이 있는 csv 파일이 있습니다. 특정 문자열에 대해 열 16을 검색하고 해당 문자열의 모든 인스턴스를 다른 문자열로 바꾸고 싶습니다. 내 프로그램의 나머지 부분은 bash 스크립트를 사용하므로 Python 검색 및 교체 대신 awk를 사용하고 싶습니다. 현재 운영 체제는 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

Market116열이 시장인 곳을 로 변경하고 싶습니다 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남아 있습니다.

답변1

awk -F '|' -v OFS='|' '$16 == "Market1" { $16 = "MarketPrime" }1' file.csv >new-file.csv

코드의 유일한 실제 문제는 입력 파일 구분 기호를 공백 |뿐만 아니라 공백으로도 설정한다는 것입니다. 이렇게 하면 공백이 데이터의 필드 구분 기호로 계산되어 올바른 필드 번호를 파악하기가 어려워집니다(일부 필드에는 가변 개수의 공백이 포함되어 있으므로).

또한 읽을 때 사용한 것과 동일한 파일 이름으로 리디렉션할 수 없습니다. 그렇게 하면 쉘이 먼저 출력 파일을 잘라내어(비게) 프로그램에서 awk읽을 데이터가 없게 됩니다.

코드에서 정규식 대체를 수행합니다. 괜찮습니다. 하지만 16번째 필드가 Market12또는 와 같을 경우 TheMarket1앵커 누락으로 인해 대체가 트리거된다는 점에 유의해야 합니다 . ^Market1$대체 표현식을 사용하거나 문자열 비교를 사용하는 것이 더 안전합니다.

위 명령은 필드 구분 기호 awk역할을 한 |다음 16번째 필드와 문자열 비교를 수행합니다. 필드가 이면 Market1으로 설정합니다 MarketPrime.

1코드 끝의 끝 부분은 awk모든 레코드(수정되거나 수정되지 않은)가 인쇄되도록 합니다.

답변2

문제는 입력 필드 구분 기호에 있습니다.

여러 필드 구분 기호(필수는 아님)를 사용하려고 하므로 각 행의 필드 수가 아래와 같이 다릅니다.

$ 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

답변3

유사한 문제에 직면할 수 있는 다른 사람들에게 명확성을 제공하려면 다음을 수행하십시오.

두 답변 모두 이 상황에 적용됩니다.

코살라 난다의 답변:

awk -F '|' -v OFS='|' '$16 == "Market1" { $16 = "MarketPrime" }1' file.csv >new-file.csv

Kusalananda의 답변을 기반으로 수정된 답변은 다음과 같습니다.

awk -F '|' '{gsub("Market1","MarketPrime",$16); print}' OFS="|" marketinfo_2018-06-26.csv > marketinfo_2018-06-26.csv

답변4

다음을 사용할 수 있습니다.

awk -F '|' -v OFS='|' '{if($16=="Market1") $16="MarketPrime" ; print }' marketinfo_2018-06-26.csv > marketinfo_2018-06-26.csv

이를 사용하면 Market1과 일치하는 스윔레인의 모든 단어를 변경할 수 있습니다. 예를 들어 17번째 단어를 변경하려면 다음과 같이 변경하면 됩니다.

awk -F '|' -v OFS='|' '{if($16=="Market1") $17="Thisiscool" ; print }' marketinfo_2018-06-26.csv > marketinfo_2018-06-26.csv

관련 정보