bash 中匹配语言代码的正则表达式

bash 中匹配语言代码的正则表达式

有一个类似的问题堆栈溢出,但它不适用于 bash。

需要什么才能使其与 bash 一起工作、与脚本/变量一起使用?

我说的是 ISO 639-1 或 ISO 639-2 代码。

我的 bash 是 GNU 4.3。

例子:

root@box ~/test2 # ls
eng  en-US  por pt-BR

该页面中的正则表达式失败:

root@box ~/test2 # ls | grep ^[a-z]{2}-[A-Z]{2}$
root@box ~/test2 # ls | grep ^[A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*$
-bash: syntax error near unexpected token `('
root@box ~/test2 # ls | grep ^[a-z]{2}(-[A-Z]{2})*
-bash: syntax error near unexpected token `('
root@box ~/test2 # ls | grep "^[a-z]{2}(-[A-Z]{2})*"

答案1

{n}不带反斜杠是扩展正则表达式的一部分,因此您需要-Egrep 的标志。另外,您想引用正则表达式,因为正如您所见,括号和大括号对 shell 有特殊含义。

$ ls
eng  en-US  por  pt-BR

$ printf "%s\n" * | grep -E '^[a-z]{2}-[A-Z]{2}$'
en-US
pt-BR

$ printf "%s\n" * | grep -E '^[A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*$'
eng
en-US
por
pt-BR

或者只使用 Bash:

$ for f in * ; do 
   [[ $f =~ ^[A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*$ ]] && printf "%s\n" "$f" ; done
eng
en-US
por
pt-BR

[[ .. ]]测试结构很特殊,大括号和括号在其中有不同的含义,实际上正则表达式必须是未引用的这里。请注意,这与[ .. ].参见例如BashGuide 关于条件的指南


[a-zA-Z]{1,8}部分匹配最多八个字母的字符串,最后一个*允许括号中的组重复任意数量,因此这foobar-foobar-foobar也将匹配类似的内容。

我们可以将模式更改为^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,3})?$仅允许包含两个或三个字母和一个尾部-xx部分的代码(如果您需要的话)。


未加引号{1,8}的是大括号扩展:

$ echo ^[A-Za-z]{1,8}
^[A-Za-z]1 ^[A-Za-z]8

未加引号[]的是文件名模式匹配(glob)...

$ touch "^a1" "^b8"
$ echo ^[A-Za-z]{1,8}
^a1 ^b8

答案2

首先,您需要regex根据 grep 要求使用引用grep 'regex'

然后,您可以使用egrepor在 grep 中使用扩展的正则表达式支持,grep -E这样就可以正常工作:

$ ls | egrep '^[a-z]{2}-[A-Z]{2}$'

或者您可以使用经典的 grep - 基本正则表达式,但您需要转义{并且}

$ ls | grep '^[a-z]\{2\}-[A-Z]\{2\}$'

根据您的问题获取这些数据

$ ls
eng
en-US
main.sh
por
pt-BR

两种 grep 情况下的输出均为

en-US
pt-BR

答案3

  1. 这是一个扩展的正则表达式,所以使用-E
  2. 如果您使用带有特殊字符的搜索模式,请引用它们

grep -E "^[a-z]{2}-[A-Z]{2}$"

相关内容