find . -maxdepth 1 -not -type d
다음과 같은 출력을 생성하는 명령을 사용합니다../filename.1.out
find 명령 출력 awk
을 . 다음을 사용하여 작동하게 했습니다../
.
find . -maxdepth 1 -not -type d | gawk 'BEGIN { FS = "(\\./)|(\\.)" } ; { print NF }'
실제로 첫 번째 대괄호 세트에서 첫 번째 백슬래시를 제거하면 작동합니다. 전임자:
find . -maxdepth 1 -not -type d | gawk 'BEGIN { FS = "(\./)|(\\.)" } ; { print NF }'
이해가 안 돼요. 제 질문은 다음을 사용하면 작동하지 않는 이유입니다.
find . -maxdepth 1 -not -type d | gawk 'BEGIN { FS = "(\./)|(\.)" } ; { print NF }'
"작동하지 않는다"는 말은 NF가 두 번째 괄호가 정규 표현식인 것처럼 숫자를 반환한다는 것입니다. 문자(모든 유형의 문자와 일치) 어쩌면 내 자신의 질문에 대답하고 있을지도 모르지만... 명령/동작을 보면 초기 백슬래시가 무시되는 것 같습니다. 실제로 경고 이스케이프 시퀀스 메시지가 있습니다 \
. 일반 "."으로 처리됩니다. 하지만 NF 인쇄를 시작하기 전까지는 그것이 무엇을 하는지 이해하지 못했습니다.
사실... 이스케이프 시퀀스에 대한 awk 문서(https://www.gnu.org/software/gawk/manual/html_node/Escape-Sequences.html#Escape-Sequences) 설명하다:
백슬래시 문자 자체는 일반적으로 포함될 수 없는 또 다른 문자이므로
\\
문자열이나 정규식에 백슬래시를 써야 합니다.
따라서 달러 기호와 일치하는 정규식을 작성하려면 FS="\\$"
?
이 글을 올리는 본래 의도는 왜 이런 일이 일어나는지 묻고자 하는 것입니다. 그럼 내가믿다내가 여러 가지를 하나로 엮었을 수도 있습니다. 내가 틀렸다면 정정해주세요.
답변1
값은 FS
두 번 스캔됩니다. 첫 번째는 문자열 값으로, 두 번째는 ERE로 스캔됩니다(참조:어휘 규칙).
또한 POSIX는 , 가 , , 중 하나 가 아니고 8진수인 , , , , , , 의 \c
동작 을 지정하지 않습니다 . 따라서 문자열이 ERE로 전달될지 ERE 로 전달될지 알 수 없습니다 .c
"
/
\ddd
d
\
a
b
f
n
r
t
v
\c
\c
c
gawk
, nawk
, 그리고Brian Kernighan 자신의 버전당신에게 c
, 그리고 동시에 mawk
당신에게 \c
:
$ for AWK in gawk mawk nawk bk-awk; do
printf '<%s>\n' "$AWK"
echo | "$AWK" -F '\.' '{print FS}'
done
<gawk>
gawk: warning: escape sequence `\.' treated as plain `.'
.
<mawk>
\.
<nawk>
.
<bk-awk>
.
는 \\
항상 로 인식되므로 \
안전할 것입니다 \\c
.
$ for AWK in gawk mawk nawk bk-awk; do
printf '<%s>\n' "$AWK"; echo | "$AWK" -F '\\.' '{print FS}'
done
<gawk>
\.
<mawk>
\.
<nawk>
\.
<bk-awk>
\.
의 문자열 값은 \\c
이므로 \c
ERE로 사용하면 원하는 결과를 얻을 수 있습니다.
답변2
\x
이는 정규식(대부분의 쉘 및 C에서와 같이)으로 처리되기 전에 큰따옴표로 묶인 문자열의 문자가 되므로 실제로 를 입력해야 \\.
합니다 \.
.
|
이것을 테스트해 보겠습니다(대체 연산자의 우선 순위가 가장 낮으므로 괄호가 필요하지 않습니다 ).
$ echo ./a.b.c | gawk 'BEGIN { FS = "\.|\./" } { for (i=1; i<=NF; i++) { print i ": " $i } }'
gawk: cmd. line:1: warning: escape sequence `\.' treated as plain `.'
1:
2:
3:
4:
5:
6:
7:
이 경고는 문자열의 이스케이프 시퀀스가 중복되었음을 알려줍니다. 따라서 FS가 하는 일은 .|./
각 문자를 분할하여 빈 필드를 만드는 것입니다.
이제 두 배로 늘리십시오 \
.
$ echo ./a.b.c | gawk 'BEGIN { FS = "\\.|\\./" } { for (i=1; i<=NF; i++) { print i ": " $i } }'
1:
2: a
3: b
4: c