Em sistemas não-GNU, o que segue explica por que \S
falha:
O \S
faz parte de um PCRE (Perl Compatible Regular Expressions). Não faz parte do BRE (expressões regulares básicas) ou do ERE (Expressões regulares estendidas) usado em shells.
O operador bash =~
dentro do teste de suporte duplo [[
usa ERE.
Os únicos caracteres com significado especial em ERE (em oposição a qualquer caractere normal) são .[\()*+?{|^$
. Não há S
como especial. Você precisa construir o regex a partir de elementos mais básicos:
regex='^b[^[:space:]]+[a-z]$'
Onde a expressão de colchete [^[:space:]]
é equivalente à \S
Expressões PCRE :
Os caracteres padrão \s
são agora HT (9), LF (10), VT (11), FF (12), CR (13) e espaço (32).
O teste seria:
var='big' regex='^b[^[:space:]]+[a-z]$'
[[ $var =~ $regex ]] && echo "$var" || echo 'none'
No entanto, o código acima corresponderá a bißß
, por exemplo. Como o intervalo [a-z]
incluirá outros caracteres além de abcdefghijklmnopqrstuvwxyz
se a localidade selecionada for (UNICODE).
Para evitar esse problema, use:
var='bißß' regex='^b[^[:space:]]+[a-z]$'
( LC_ALL=C;
[[ $var =~ $regex ]]; echo "$var" || echo 'none'
)
Por favor, esteja ciente de que o código irá corresponder aos caracteres apenas na lista: abcdefghijklmnopqrstuvwxyz
na última posição do personagem, mas ainda irá coincidir com muitos outros no meio: por exemplo, bég
.
Ainda assim, esse uso de LC_ALL=C
afetará o outro intervalo de regex: [[:space:]]
corresponderá somente aos espaços do idioma C.
Para resolver todos os problemas, precisamos manter cada regex separado:
reg1=[[:space:]] reg2='^b.*[a-z]$' out=none
if [[ $var =~ $reg1 ]] ; then out=none
elif ( LC_ALL=C; [[ $var =~ $reg2 ]] ); then out="$var"
fi
printf '%6.8s\t|' "$out"
Qual lê como:
- Se a entrada (var) não tiver espaços (no local atual), então
- verifique se começa com
b
e termina ema-z
(na localidade C).
Observe que ambos os testes são feitos nos intervalos positivos (em oposição a um intervalo "não"). A razão é que negar um par de personagens abre muito mais correspondências possíveis. O UNICODE v8 tem 120.737 caracteres já atribuídos. Se um intervalo nega 17 caracteres, ele aceita outros 120720 caracteres possíveis, que podem incluir muitos caracteres de controle não imprimíveis.
Deve ser uma boa ideia limitar o intervalo de caracteres que os personagens do meio podem ter (sim, esses não serão espaços, mas podem ser qualquer outra coisa).