파이프를 열 구분 기호로 사용하고 큰따옴표를 텍스트 구분 기호로 사용하여 데이터베이스에서 플랫 파일로 데이터를 추출하고 있습니다.
데이터 파일은 다음과 같습니다.
"164829" | "collection 1" | "wood plank 2" x 4" long" | "23.5"
"2017"|"S"|"221318"|"WE"|"20170118"|"Someones name"|"20170215"|"1785"|"009"|"20170215"|"182339"|"99536"|"00090"|"LOCAL00"|"930N"|"2017"|"6100"|"0000880"|1.000|0.000|"EA"|" "|" "|" "|" "|"005"|"00000000"|" "|" "|"1785"|"50228"|"R"|"2017"|"NMT CAUTION| 5" X 3" NAT ON BLK"|" "|" "|"USD"|"7444"|" "|"000"|"COIN"|"04"|35.00|"00"
두 번째 큰따옴표로 데이터(텍스트 구분 기호 제외)를 이스케이프할 수 있는 모든 경우를 찾을 수 있는 명령/스크립트는 무엇입니까?
최종 결과는 다음과 같아야 합니다.
"164829" | "collection 1" | "wood plank 2"" x 4"" long" | "23.5"
"2017"|"S"|"221318"|"WE"|"20170118"|"Someones name"|"20170215"|"1785"|"009"|"20170215"|"182339"|"99536"|"00090"|"LOCAL00"|"930N"|"2017"|"6100"|"0000880"|1.000|0.000|"EA"|" "|" "|" "|" "|"005"|"00000000"|" "|" "|"1785"|"50228"|"R"|"2017"|"NMT CAUTION| 5"" X 3"" NAT ON BLK"|" "|" "|"USD"|"7444"|" "|"000"|"COIN"|"04"|35.00|"00"
답변1
정규식만 사용하면 약간 까다롭지만 몇 단계만 거치면 완료할 수 있습니다. 여기에 내가 사용하는 Perl 스크립트가 있습니다(예측을 사용하기 때문에 sed를 사용할 수 없습니다).
perl -pe 's/(?:(?:\||^)[ ]*"(.*?)\"[ ]*(?=\||$))/~~\1~~/gm;s/"/""/g;s/~~(.*?)~~/~~"\1"~~/g;s/~~~~/|/g;s/~~//g' inputfile.txt
( perl -pi -e
입력 파일을 편집하려는 경우 사용)
스크립트는 다음 단계를 수행합니다.
- 외부 공백 텍스트를 무시하고 |"{...}"|(줄 시작) "{...}"| 또는 |"{...}"(줄 끝) 내의 모든 항목을 찾습니다. 외부 비트를 다음으로 대체합니다
~~
. (텍스트 내부에 없는 것으로 알려진 것을 사용했습니다.) - 나머지 따옴표를 모두 큰따옴표로 바꿉니다.
- 모든 내부
~~{...}~~
시퀀스를 다음으로 대체하십시오.~~"{...}"~~
- 모든
~~~~
시퀀스(모든 내부 시퀀스)를 다음으로 대체합니다.|
- 나머지 모든
~~
시퀀스 제거(줄의 시작과 끝 부분)
각 단계가 실행되고 다음 테스트 텍스트가 제공됩니다.
"164829" | "collection 1" | "wood plank 2" x 4" long" | "23.5"
"939485"|"collect "name""|"more items with | " and ""|"294.5""
각 단계 후에 다음과 같은 출력을 얻습니다.
$ perl -pe 's/(?:(?:\||^)[ ]*"(.*?)\"[ ]*(?=\||$))/~~\1~~/gm;' testinput.txt
~~164829~~~~collection 1~~~~wood plank 2" x 4" long~~~~23.5~~
~~939485~~~~collect "name"~~~~more items with | " and "~~~~294.5"~~
$ perl -pe 's/(?:(?:\||^)[ ]*"(.*?)\"[ ]*(?=\||$))/~~\1~~/gm;s/"/""/g;' testinput.txt
~~164829~~~~collection 1~~~~wood plank 2"" x 4"" long~~~~23.5~~
~~939485~~~~collect ""name""~~~~more items with | "" and ""~~~~294.5""~~
$ perl -pe 's/(?:(?:\||^)[ ]*"(.*?)\"[ ]*(?=\||$))/~~\1~~/gm;s/"/""/g;s/~~(.*?)~~/~~"\1"~~/g;' testinput.txt
~~"164829"~~~~"collection 1"~~~~"wood plank 2"" x 4"" long"~~~~"23.5"~~
~~"939485"~~~~"collect ""name"""~~~~"more items with | "" and """~~~~"294.5"""~~
$ perl -pe 's/(?:(?:\||^)[ ]*"(.*?)\"[ ]*(?=\||$))/~~\1~~/gm;s/"/""/g;s/~~(.*?)~~/~~"\1"~~/g;s/~~~~/|/g;' testinput.txt
~~"164829"|"collection 1"|"wood plank 2"" x 4"" long"|"23.5"~~
~~"939485"|"collect ""name"""|"more items with | "" and """|"294.5"""~~
$ perl -pe 's/(?:(?:\||^)[ ]*"(.*?)\"[ ]*(?=\||$))/~~\1~~/gm;s/"/""/g;s/~~(.*?)~~/~~"\1"~~/g;s/~~~~/|/g;s/~~//g' testpipe.txt
"164829"|"collection 1"|"wood plank 2"" x 4"" long"|"23.5"
"939485"|"collect ""name"""|"more items with | "" and """|"294.5"""
답변2
큰따옴표는 실제 큰따옴표(" vs ")가 아닙니다.
실제 큰따옴표 "를 사용하면 sed로 이를 시도해 볼 수 있습니다(데이터에 @가 없다고 가정).
sed 's/" | "/@/g;s/"/""/g;s/^"//;s/"$//;s/@/" | "/g' infile
답변3
이 포럼의 Bahrat는 문제 해결에 매우 가까운 답변을 게시했지만 어떻게든 이 게시물에서 삭제되었습니다(아래 코드). 유일한 문제는 문자열의 파이프를 처리할 수 없다는 것입니다(예: "25" | "데이터를 연결하려면 하나를 사용해야 합니다" | "부록 1" | 20 | "마지막 항목"). 그는 오늘 게시하기로 되어 있었지만 그 스레드가 삭제됐나요?
awk -v FS='|' -v OFS='|' '{for(i=1;i<=NF;i++){gsub(/"/,"\"\"",$i);sub(/"/,"",$i);sub(/"[^"]*$/,"",$i)}print}' myfile > myfile3
답변4
입력 -
"2017"|"S"|"221318"|"우리"|"20170118"|"누군가의 이름"|"20170215"|"1785"|"009"|"20170215"|"182339"|"99536" |" 00090"|"Local00"|"930N"|"2017"|"6100"|"0000880"|1.000|0.000|"EA"|""|""|""|""|"005"| "00000000" |" "|" "|"1785"|"50228"|"R"|"2017"|"NMT NOTE| 5" X 3" NAT ON BLK"|" "|" "|"USD"| |" "|"000"|"코인"|"04"|35.00|"00"
주문하다:
awk -v RS='[[:blank:]]*[[:blank:]]*[|][[:blank:]]*|[[:blank:]]*[\n][[:blank:]]*' '{ if ($0 !~ /(^"([^"]|"")*"$)/) { gsub(/\"/,"\"\"");sub(/^"/,"");sub(/"$/,"") } printf "%s%s", $0, RT}' file.txt
출력 -
"2017"|"S"|"221318"|"우리"|"20170118"|"누군가의 이름"|"20170215"|"1785"|"009"|"20170215"|"182339"|"99536" |" 00090"|"Local00"|"930N"|"2017"|"6100"|"0000880"|1.000|0.000|"EA"|""|""|""|""|"005"| "00000000" |" "|" "|"1785"|"50228"|"R"|"2017"|"NMT NOTE| 5"" X 3"" NAT ON BLK"|" "|" "|"USD "|" 7444"|""|"000"|"코인"|"04"|35.00|"00"