如何使用 awk 检查线上的第一个模式?
How can to check for first pattern on the line with awk?
这里有一个令人困惑的(对我来说)的例子。这个 awk
表达式给出了期望的结果并打印:“match
”
$ echo -e "<?xml version="1.1" encoding="UTF-8" standalone="no"?>\n<databaseChangeLog" |
awk -e'/[[:space:]]*<?xml /{ print "match"; } { quit 0; }'
match
$
我们实际上希望任何匹配项都是行中的第一个模式。据我所知,这应该是string/line anchor,^
的开头。然而添加 ^
失败,如图所示:
$ echo -e "<?xml version="1.1" encoding="UTF-8" standalone="no"?>\n<databaseChangeLog" |
awk -e'/^[[:space:]]*<?xml /{ print "match"; } { quit 0; }'
$
$ # NO match
使用 gawk
,版本:
$ awk --version
GNU Awk 5.0.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.2.0)
Copyright (C) 1989, 1991-2019 Free Software Foundation.
...
缺少什么?
您将 ^
添加到您的输入中,而不是将其添加到您的代码中应该与输入匹配的正则表达式中,即您做了:
$ echo '^foobar' | awk '/bar/'
^foobar
而不是:
$ echo 'foobar' | awk '/^bar/'
$
您也在使用 ?
正则表达式元字符,但想要文字 ?
而不是,而您正尝试使用不存在的关键字 quit
,而我假设您的意思是exit
(所以你的代码实际上做的是连接一个未定义的变量与数字 0
导致字符串 0
然后你只是丢弃)但你只退出 0
这是默认的,所以这都是多余的。
我认为这可能是您想要做的:
awk '/^[[:space:]]*<\?xml /{ f=1; exit } END{ if (f) print "match"; exit !f }'
例如:
$ printf '%s\n' '<?xml version="1.1" encoding="UTF-8" standalone="no"?>' '<databaseChangeLog' |
awk '/^[[:space:]]*<\?xml /{ f=1; exit } END{ if (f) print "match"; exit !f }'
match
$ echo $?
0
$ printf '%s\n' 'foo<?xml version="1.1" encoding="UTF-8" standalone="no"?>' '<databaseChangeLog' |
awk '/^[[:space:]]*<\?xml /{ f=1; exit } END{ if (f) print "match"; exit !f }'
$ echo $?
1
以上内容适用于任何 POSIX awk。如果您有一个不支持 POSIX 字符 类 的非常旧的 awk,那么只需将 [[:space:]]
更改为 [ \t]
即可在任何 awk 中使用。
同时考虑将匹配或不匹配打印到 stderr:
$ printf '%s\n' '<?xml version="1.1" encoding="UTF-8" standalone="no"?>' '<databaseChangeLog' |
awk '/^[[:space:]]*<\?xml /{ f=1; exit } END{ print (f ? "" : "no ") "match" | "cat>&2"; exit !f }'
match
$ printf '%s\n' 'foo<?xml version="1.1" encoding="UTF-8" standalone="no"?>' '<databaseChangeLog' |
awk '/^[[:space:]]*<\?xml /{ f=1; exit } END{ print (f ? "" : "no ") "match" | "cat>&2"; exit !f }'
no match
这里有一个令人困惑的(对我来说)的例子。这个 awk
表达式给出了期望的结果并打印:“match
”
$ echo -e "<?xml version="1.1" encoding="UTF-8" standalone="no"?>\n<databaseChangeLog" |
awk -e'/[[:space:]]*<?xml /{ print "match"; } { quit 0; }'
match
$
我们实际上希望任何匹配项都是行中的第一个模式。据我所知,这应该是string/line anchor,^
的开头。然而添加 ^
失败,如图所示:
$ echo -e "<?xml version="1.1" encoding="UTF-8" standalone="no"?>\n<databaseChangeLog" |
awk -e'/^[[:space:]]*<?xml /{ print "match"; } { quit 0; }'
$
$ # NO match
使用 gawk
,版本:
$ awk --version
GNU Awk 5.0.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.2.0)
Copyright (C) 1989, 1991-2019 Free Software Foundation.
...
缺少什么?
您将 ^
添加到您的输入中,而不是将其添加到您的代码中应该与输入匹配的正则表达式中,即您做了:
$ echo '^foobar' | awk '/bar/'
^foobar
而不是:
$ echo 'foobar' | awk '/^bar/'
$
您也在使用 ?
正则表达式元字符,但想要文字 ?
而不是,而您正尝试使用不存在的关键字 quit
,而我假设您的意思是exit
(所以你的代码实际上做的是连接一个未定义的变量与数字 0
导致字符串 0
然后你只是丢弃)但你只退出 0
这是默认的,所以这都是多余的。
我认为这可能是您想要做的:
awk '/^[[:space:]]*<\?xml /{ f=1; exit } END{ if (f) print "match"; exit !f }'
例如:
$ printf '%s\n' '<?xml version="1.1" encoding="UTF-8" standalone="no"?>' '<databaseChangeLog' |
awk '/^[[:space:]]*<\?xml /{ f=1; exit } END{ if (f) print "match"; exit !f }'
match
$ echo $?
0
$ printf '%s\n' 'foo<?xml version="1.1" encoding="UTF-8" standalone="no"?>' '<databaseChangeLog' |
awk '/^[[:space:]]*<\?xml /{ f=1; exit } END{ if (f) print "match"; exit !f }'
$ echo $?
1
以上内容适用于任何 POSIX awk。如果您有一个不支持 POSIX 字符 类 的非常旧的 awk,那么只需将 [[:space:]]
更改为 [ \t]
即可在任何 awk 中使用。
同时考虑将匹配或不匹配打印到 stderr:
$ printf '%s\n' '<?xml version="1.1" encoding="UTF-8" standalone="no"?>' '<databaseChangeLog' |
awk '/^[[:space:]]*<\?xml /{ f=1; exit } END{ print (f ? "" : "no ") "match" | "cat>&2"; exit !f }'
match
$ printf '%s\n' 'foo<?xml version="1.1" encoding="UTF-8" standalone="no"?>' '<databaseChangeLog' |
awk '/^[[:space:]]*<\?xml /{ f=1; exit } END{ print (f ? "" : "no ") "match" | "cat>&2"; exit !f }'
no match