awk
부분 문자열의 위치와 길이가 원본 $0의 필드 위치를 기준으로 하는 경우 $0의 부분 문자열을 추출하는 방법은 무엇입니까?
이는 첫 번째 항목을 제거하는 것과 사실상 동일합니다.선두필드와 마지막추적하다필드와 원래 $0으로 시작하는 모든 필드에 대한 선행 및 후행 구분 기호
예: 현재 범위는 US$4 ~ US$8(포함)이라는 것만 알고 있습니다.
구분 기호는 공백 및/또는 단일 쉼표입니다. " , "
아니면 ","
... 그리고 선행 구분 기호는 무시됩니다.
Input: " a a a X marks the start, Y marks the end "
Expected Output: "X marks the start, Y"
답변1
awk는 필드 위치나 구분 기호 문자열을 기억하지 않습니다. 필드 위치를 수동으로 찾아야 합니다. 별로 어렵지 않습니다.
echo " a b c X marks the start, Y marks the end " |
awk '{
i=1; n=1; tmp=$0; # i=field number, n=column number
while (match(tmp, / *, *| +/)) {
A[i]=n; B[i]=n+RSTART-1; # A[i],B[i] = start,end of delimiter i
++i; n+=RSTART+RLENGTH-1;
tmp=substr(tmp,RSTART+RLENGTH)
}
print substr($0, A[5], B[9]-A[5]) # start at 4+1 because the first field is empty
}'
답변2
구분 기호로 탭 문자가 없는 한 이는 해결책이 될 수 있습니다.
#!/usr/bin/awk -f
{
start = index($0, " " $4 " ")
stop = index($0, " " $8 " ")
print substr($0, start+1, stop - start + length($8))
}
답변3
현재로서는 선행 구분 기호가 있거나 없는 데이터에 대해 작동하지만 필드에 "정규식에 민감한" 데이터가 포함되어 있으면 실패합니다. 해결책은 각 필드를 정규식 점 .{필드 필드}...로 바꾸는 것입니다.이것은 링크입니다 이와 같은 버전에서는... 투박하지만 위의 문제와 충돌하지 않습니다.
awk 'BEGIN { FS = "([ \t]+)|([ \t]*,[ \t]*)" }
{ # Ignore leading delimiter, if present
hasLeadDlm = match($0, "^("FS")")
LeadDlm = substr($0, 1, RLENGTH)
if (hasLeadDlm) { sub("^("FS")", ""); } # delete leading whitespace
sub("^"$1"("FS")"$2"("FS")"$3"("FS")", "") # delete leading fields
match( $0, "^"$1"("FS")"$2"("FS")"$3"("FS")"$4"("FS")"$5)
print substr($0, 1, RLENGTH)
}' <<< \
"a X a X marks the start, ssY marks the end
a X a X marks the start, sY marks the end
a X a X marks the start, Y marks the end
a X a X marks the start ,Y marks the end
a X a X marks the start,sssY marks the end"