이 답변은되도록 CSV 파일 (샘플 데이터로) 아름답게 일관되고 간단 있다고 가정
- 필드는 항상 큰 따옴표가있다.
- 문자열에 포함 된 큰 따옴표를 나타내는
"…""…"
과 같은 입력란은 절대로 존재하지 않습니다.
- 따옴표 사이에는 쉼표가있는 입력란이 없습니다 (
"this,that"
). sed 's/^\("[^"]*",\)\{4\}"\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}",/&"YYYY-MM-DD HH:MM:SS",/'
하는의 조각으로 해당 검색 패턴을 분할하자 : 라인의
^\("[^"]*",\)\{4\}
경기 시작
그 전제 조건을 감안할 때
이 sed
스크립트는 작업을 수행 뒤에 오는 것 : 큰 따옴표의 4 반복, 0 개 이상의 큰 따옴표의 순서, 두 배 따옴표와 쉼표.
즉, 처음 네 개의 필드를 식별합니다.
"\([0-9]\{1,3\}\.\)\{3\}
일치 따옴표
후 뒤에 도트 1-3 진수의 3 개 반복 -는 IPv4의 처음 세 쌍둥이는 점으로 구분 된 십진수 주소를.따옴표와 쉼표
[0-9]\{1,3\}",
경기 1-3 진수 -는 IPv4의 마지막 삼중는 점으로 구분 된 십진수 주소 플러스 필드의 끝을.
명확히 말하면, 처리해야하는 CSV 파일의 각 고유성에 대해 정규 표현식을 수정해야합니다. 그것은 사소한 것이 아닙니다. (GNU와 BSD sed
모두 -E
으로 사용) 확장 된 정규 표현식을 사용
, 당신은 쓸 수 :
sed -E 's/^("(([^"]*"")*[^"]*)",){4}"([0-9]{1,3}\.){3}[0-9]{1,3}",/&"YYYY-MM-DD HH:MM:SS",/'
처음 4 개 필드를 인식하는 패턴이 이전보다 더 복잡하다. 큰 따옴표, 두 개 이상의 큰 따옴표, 두 개 이상의 큰 따옴표, 두 개 이상의 큰 따옴표, 큰 따옴표 및 쉼표 순으로 4 번 반복됩니다. 데이터 파일을 감안할 때
sed 's/^\("\(\([^"]*""\)*[^"]*\)",\)\{4\}"\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}",/&"YYYY-MM-DD HH:MM:SS",/'
가 :
이
"12345","","","None","192.168.2.1","qqq","000"
"67890","ABC-1234-5678","9.9","Low","192.168.2.1","qqq","000"
"23456","Quaternions","2.3","Pisces","Heredotus","qqq","000"
"34567","Commas, oh commas!","3.14159","""Quotes"" quoth he","192.168.99.37","zzz","011"
"45678","Commas, oh commas!","3.14159","""Quote me"",""or not""","192.168.99.37","zzz","011"
표시되는 첫 번째 스크립트는 출력을 생성
또한 백 슬래시의 자유 뿌리 클래식 sed
(기본 정규 표현식)의 것을 쓸 수 있습니다 :
"12345","","","None","192.168.2.1","YYYY-MM-DD HH:MM:SS","qqq","000"
"67890","ABC-1234-5678","9.9","Low","192.168.2.1","YYYY-MM-DD HH:MM:SS","qqq","000"
"23456","Quaternions","2.3","Pisces","Heredotus","qqq","000"
"34567","Commas, oh commas!","3.14159","""Quotes"" quoth he","192.168.99.37","zzz","011"
"45678","Commas, oh commas!","3.14159","""Quote me"",""or not""","192.168.99.37","zzz","011"
첫 번째 두 줄은 올바르게 매핑됩니다. 에드; 세 번째는 바뀌지 않지만 마지막 두 개는 매핑되어 있어야하고 그렇지 않습니다. Heredotus이 (제대로) 수정되지 않습니다
"12345","","","None","192.168.2.1","YYYY-MM-DD HH:MM:SS","qqq","000"
"67890","ABC-1234-5678","9.9","Low","192.168.2.1","YYYY-MM-DD HH:MM:SS","qqq","000"
"23456","Quaternions","2.3","Pisces","Heredotus","qqq","000"
"34567","Commas, oh commas!","3.14159","""Quotes"" quoth he","192.168.99.37","YYYY-MM-DD HH:MM:SS","zzz","011"
"45678","Commas, oh commas!","3.14159","""Quote me"",""or not""","192.168.99.37","YYYY-MM-DD HH:MM:SS","zzz","011"
주, 마지막 두 줄은 (정확하게도) IP 주소 이후에 추가 날짜 문자열을 얻을 :
두 번째와 세 번째 명령을 생산하고 있습니다.
마지막 정규식은 희미한 것이 아닙니다.
IP 주소가 각 구성 요소의 0..255 범위의 숫자와 일치하며 앞에 0이없는 것으로 주장하려는 경우 분명히 정규 표현식의 IP 주소 일치 부분을 강화해야합니다. 그것은 할 수있다; 그것은 예쁘지 않다. 그것은 확장 된 정규 표현식을 수행하는 가장 쉬운 방법입니다 :
([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])
당신은 이전에 표시된 정규 표현식에 각 [0-9]{3}
단위 대신에이 장치를 사용하십시오.
여전히 큰 따옴표로 묶지 않은 필드는 처리하지 않습니다.
또한 date
명령에서 대체 할 값을 결정하지 않습니다. 즉 (아니라면 초 후) 루틴 쉘 스크립트 신중하게 따옴표 관리에 행할 :
dt=$(date +'%Y-%m-%d %H:%M:%S')
sed -E 's/^("(([^"]*"")*[^"]*)",){4}"([0-9]{1,3}\.){3}[0-9]{1,3}",/&"'"$dt"'",/'
'…"'"$dt"'",/'
시퀀스는 단일 인용 문자열로 밖으로 시작 무엇의 일부입니다.첫 번째 큰 따옴표는 문자열의 단순한 데이터입니다. 다음 작은 따옴표가 인용 부호를 끝내고 "$dt"
은 쉘 큰 따옴표 안에 date
의 값을 삽입합니다 (따라서 공간이 문제가되지 않도록). 작은 따옴표는 작은 따옴표를 다시 시작하고 쉼표 및 쉼표를 추가합니다. 문자열 앞의 슬래시 (sed
인수)가 종료됩니다.
왜 awk을 사용할 수 없습니까? 그것은 훨씬 더 적합 할 것입니다. –
$ 5가 IP 주소가 아닌 행에서 어떻게해야합니까? –
CSV 파일은 얼마나 깨끗한가요? 주변에 큰 따옴표가없는 필드가 있습니까? ''... ""... "'문자열에 포함 된 큰 따옴표를 표시하는 필드가 있습니까? 따옴표 사이에 쉼표가있는 필드가 있습니까 (''this, that "')? 그것은 치명적인 것은 아니지만, 'YYYY-MM-DD HH : MM : SS'의 값은 변수 (예 :'date + '% Y- % m- % d % H : %의 출력) M : % S''이 캡쳐되어'sed' 명령으로 대체됩니까? –