Bash는 구분 기호를 사용하여 이전 개행 문자를 읽습니다.

Bash는 구분 기호를 사용하여 이전 개행 문자를 읽습니다.

특정 필드를 추출해야 하는 CSV가 있습니다. csv는 파이프로 구분되며( |) 큰따옴표( ")는 일부 텍스트에서 텍스트 필드와 줄 바꿈을 보호하는 데 사용됩니다(문제임).

예를 들어.

"aaa"|"111"|"!!!"|""
"bbb"|"222"|"@@
@"|""
"ccc"|"333"|"###"|""

각 레코드의 두 번째 필드를 추출하고 싶습니다.

111
222
333

bash 스크립트를 사용하여 파일을 읽고 있는데 개행 문자가 지정되어 있어도 read개행 문자에 도달하면 명령이 중지되는 것 같습니다. -d이는 위의 예에서 내 스크립트가 레코드 1(내가 사용하는 read -d \| varname)을 올바르게 처리하지만 개행 문자를 세 번째 필드의 일부로 인식하지 못하기 때문에 레코드 2를 올바르게 처리하지 못한다는 것을 의미합니다. 이제 @"|""새로운 기록으로 간주 되었으므로 모든 지옥이 풀렸습니다.

이 목적 으로 이것을 사용할 수 있습니까 read? 아니면 대안을 고려해야 합니까?

내가 썼다하늘read사용하는 설정을 시험해보고 웹을 검색해 보세요. 흥미롭게도 나와 똑같은 입력 파일에 문제가 있는 사람을 만났는데 문제는 Excel에 있었습니다.

답변1

readCSV를 처리할 수 있는 명령이 내장된 셸의 경우 ksh93대신 다음을 사용할 수 있습니다 bash.

$ while IFS='|' read -rS a b c; do printf '%s\n' "$b"; done < file
111
222
333

형식을 처리할 수 있는 형식으로 변환하려면 bash다음 read을 수행하세요.

< file ksh93 -c 'while IFS="|" read -rSA a; do
                   printf "%s|" "${a[@]//[\|]/\\\0}"
                   printf "\0"
                 done' |
       bash -c 'while IFS="|" read -d "" a b c; do
                  printf "%s\n" "$b"
                done'

답변2

실제로 적합한 CSV 파서를 사용해야 합니다. 예를 들어, 다음과 함께 제공되는 Ruby를 사용합니다.

ruby -rcsv -e 'CSV.foreach("file", :col_sep => "|") {|row| p row; puts row[1]}'

우리는 얻었다

["aaa", "111", "!!!", ""]
111
["bbb", "222", "@@\n@", ""]
222
["ccc", "333", "###", ""]
333

두 번째 줄에 개행 문자가 포함되어 있는 것을 볼 수 있습니다. p row해당 "디버그" 줄을 제거하려면 제거하세요 .

답변3

좋아요, 그래서 저에게 가장 좋은 해결책은(하지만 취향의 문제인 것 같아요) PHP를 사용하는 것입니다 fgetcsv. 왜냐하면 저는 이 서버에 이미 PHP가 설치되어 있기 때문입니다. 불행하게도 bash read명령은 PHP 함수처럼 개행 문자를 처리하지 않습니다. 추가 구분 기호(예: "")를 자동으로 인식합니다.

견본:

<?php
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 10000, "|")) !== FALSE) {
        $num = count($data);
        echo "$num fields in line $row:\n";
        $row++;
        for ($c=0; $c < $num; $c++) {
            echo $c + 1 . ": " . $data[$c] . "\n";
        }
    }
    fclose($handle);
}
?>

출력(내 원래 질문과 유사):

4 fields in line 1:
1: aaa
2: 111
3: !!!
4: 
4 fields in line 2:
1: bbb
2: 222
3: @@
@
4: 
4 fields in line 3:
1: ccc
2: 333
3: ###
4: 

관련 정보