탭으로 구분된 열이 있는 텍스트 파일이 있는데 awk를 사용하여 처리하고 싶습니다.
다음은 그러한 파일의 예입니다.
size=1\tname=foo\tweight=1.2
weight=2.5\tname=bar\tsize=2
내가 달성하고 싶은 것은 소수점 네 자리와 유사한 내용을 가진 열의 숫자 값을 정규화 $field_name=<number>
하고 나머지는 변경하지 않고 유지하는 것입니다. 여기에는 $field_name
awk에 전달된 쉘 변수가 있으며 그 값을 정규 표현식에 사용하고 싶습니다.
다음은 스니펫입니다(물론 작동하지 않습니다). 나는 특히 다른 도구(sed, Perl, Python 등)를 사용하는 솔루션보다는 다음 awk 스크립트의 5행을 수정하는 데 관심이 있습니다.
$ cat "${file}" \ # 1
| awk -F "\t" -v field_name="${external_var}" ' # 2
{ # 3
for (i = 1; i <= NF; i++) { # 4
if ($i ~ /$field_name=[0-9]*.?[0-9]+/) { # 5
split($i, kv, "=") # 6
$i = sprintf("%s=%.4f", kv[1], kv[2]) # 7
} # 8
} # 9
print $0 # 10
}'
답변1
이는 다음과 같아야 합니다:
if ($i ~ field_name "=[0-9]*.?[0-9]+") ...
또는:
regexp = field_name "=[0-9]*.?[0-9]+"
if ($i ~ regexp) ...
.
단일 문자는 모두 일치됩니다 . 리터럴을 일치시키려면 (큰따옴표 안에 작성해야 함 ) 또는 를 포함 .
해야 합니다 .regexp
\.
\\.
[.]
regexp = field_name "=[0-9]*\\.?[0-9]+"
또한 정규식을 고정하고 싶기를 바랍니다.
regexp = "^" field_name "=[0-9]*\\.?[0-9]+$"
기타 참고사항:
cat "${file}"
$file
UUOC이기 때문에 시작 시 작동하지 않고-
파일을 열 수 없는 경우 계속 실행된다는 단점(리디렉션을 통해)도 있습니다.awk
-v field_name="$external_data"
백슬래시를 끊습니다. 문제 없는 또 다른 방법은 환경 변수를 사용하고FIELD="$external_data" awk ...
이를 as에서 참조하는 것입니다.awk
ENVIRON["FIELD"]
- 의 내용이
field_name
그대로 에 복사되므로regexp
정규식으로 처리되므로$external_data
정규식 연산자( ... )를 포함 하면.+*?{}()[]\^%
제대로 작동하지 않을 수 있습니다 . - 일부 로케일 및
awk
구현 에서는[0-9]
단순한 것보다 더 많은 문자가 일치합니다0123456789
(입력에 나타날 가능성이 없는 (ASCII가 아닌) 문자인 것으로 의심되지만).
그리고 perl
:
FIELD=size <"$file" perl -lpe '
s{
(?<![^\t]) # not-preceded by a non-TAB
\Q$ENV{FIELD}=\E # contents of $FIELD taken literally
\K # matched portion starts here
\d*\.?\d+
(?![^\t]) # not followed by a non-TAB
}{
sprintf "%.4f", $&
}gxe'
awk
이는 위에서 설명한 문제를 전혀 나타내지 않습니다(또한 텍스트와 바이너리 데이터의 혼합 또는 사용자의 로케일과 다른 문자 집합으로 인코딩된 텍스트 등 잘못된 텍스트를 포함하는 입력보다 낫습니다 ).