텍스트 로그 파일이 있습니다
$ cat aaa
673 20160405 root "/path_to/gis/20160401/20160301_placement_map_org.dbf" ""
673 20160405 root "/path_to/gis/20160401/20160310_20160401ent_map_org.dbf" ""
790890 20170201 jle "/path_to/gis/20160401/Pina (Asc) 20160401 Rapid Report.kmz" ""
5883710 20160406 dho "/path_to/gis/20160401/20160401_Pina_Asc_Rapid_Report_Minesouth.pdf" ""
673 20160405 dho "/path_to/gis/20160401/20160310_20160401 placement map org.dbf" ""
이제 내 스크립트는 파일의 전체 경로만 출력합니다.
#!/bin/bash
function nodatechk() {
arr=("$@")
for ((i=3;i<${#arr[@]};i+=5));
do
echo "${i}" "${arr[i]}"
done
}
r=( $(grep gis aaa) )
nodatechk "${r[@]}"
세 번째 줄(및 다섯 번째 줄)에 큰따옴표가 있더라도 요소에 공백이 있기 때문에 출력이 깨졌습니다.
이 문제를 어떻게 해결할 수 있나요? (그런데, awk나 cut을 사용하여 열을 인쇄할 수 있다는 것을 알고 있지만 이 경우에는 grep을 사용하고 싶습니다.) 감사합니다.
답변1
문제의 근본 원인은 다음과 같습니다.
r=( $(grep gis aaa) )
시도해 보면 다음과 같은 내용이 즉시 표시됩니다.
printf '<%s>\n' $(grep gis aaa)
"$IFS" 내의 문자(기본적으로 공백, 탭, 줄 바꿈)를 기준으로 분할됩니다.
그리고파일의 값을 와일드카드에 노출합니다. 그러면 몇 가지 *
, ?
및 […]
(어떤 것은 비밀번호의 파일 목록과 몇 가지 쉘 옵션에 따라 달라집니다)이 변환됩니다.
한 가지(권장되지 않음) 해결책은 IFS
분할 문자로 변경하는 것입니다.그리고분할을 비활성화하는 와일드카드:
IFS=$'\n'; set -f; r=( $(grep gis aaa) )
그러나 더 간단한 해결책은 셸에서 이미 제공하는 기능을 사용하는 것입니다.
readarray -t r <(grep gis aaa)
이는 개행 문자로 분할됩니다(경로 이름에 개행 문자가 없다고 가정).
그런 다음 줄을 공백 분할 및 와일드카드에 노출시킬 수 있는 각 부분을 얻기 위해 각 줄을 다시 분할하지 않도록 줄의 선행 및 후행 부분을 제거해 보겠습니다.
"/
각 줄의 처음부터 (큰따옴표 및 슬래시)까지의 모든 항목과 "
(큰따옴표 및 공백)부터 끝까지의 모든 항목을 제거하면 깨끗한 경로 이름을 얻을 수 있습니다.
#!/bin/bash
function nodatechk() {
for l do
l="/${l#*\"/}" # Remove leading text up to `"/`
l=${l%\" *} # Remove trailing text from `" `
printf '%s\n' "$l"
done
}
readarray -t r < <(grep gis aaa)
nodatechk "${r[@]}"
답변2
유일한 grep
해결책은
grep gis aaa | grep -o '^[^"]*"[^"]*"' | grep -o '"[^"]*"$'
첫 번째는 grep
귀하의 질문에 있는 것과 동일합니다. 분명히 gis
(행의 어느 곳이든)을 포함하는 행을 선택합니다 . 두 번째 grep,
grep -o '^[^"]*"[^"]*"'
행(예: 열 1~4)에서 첫 번째로 인용된 문자열을 포함하여 모든 항목과 일치합니다.
그리고, 이로 인해 -o
옵션, 출력오직그 말. 세 번째 grep,
grep -o '"[^"]*"$'
행(이 시점에서 원래 행의 열 4)에서 마지막으로 인용된 문자열과 일치하고 해당 문자열만 출력합니다.
PS 파일의 각 열 쌍 사이에 탭 문자가 있고 값에 탭 문자가 포함되어 있지 않은 경우 네 번째 열을 얻는 쉬운 방법은 다음과 같습니다.
awk -F'\t' '/gis/ { print $4 }' aaa
답변3
나는 읽었다이 게시물나는 "eval"을 사용하여 이 문제를 해결했습니다. 따라서 다음 줄을 변경했습니다.
r=( $(grep gis aaa) )
도착하다
eval r="( $(grep gis aaa) )"