Suponha que exista um script PHP de teste simples:
<?php
$a = ($argc == 2 ? $argv[1] : 10);
for ($i = 0; $i < $a; $i++) {
echo '.';
}
echo PHP_EOL;
Agora, eu faço um grep ou um sed condicional no arquivo:
grep '<' test.php
produz as duas linhas contendo o <
. Isso está claro.
grep '\?' test.php
produz as duas linhas contendo o ponto de interrogação. Isso está claro.
grep '<\?' test.php
retorna todas as linhas - por quê? Eu esperava que ele produzisse apenas a primeira linha. Mas talvez o <
deva ser escapado, o que produz outra saída inesperada.
sed -n '/pattern/p' test.php
produz os mesmos resultados.
Tentei obter uma resposta em https://regex101.com/ , mas para minha surpresa, o site mostra o que espero. Além disso, uma implementação PHP rápida e suja grep
produz o que eu espero:
<?php
if (($fh = fopen($argv[2], 'r')) !== false) {
while ($line = fgets($fh)) {
if (mb_ereg($argv[1], $line) !== false) echo $line;
}
}
Minha pergunta é: Qual é o raciocínio por trás dessas partidas em grep
e sed
?
grep
O comportamento padrão do é interpretar expressões regulares como expressões regulares básicas (BREs). Estes não são suportados?
como um símbolo especial; é o personagem básico:assim dá o resultado que você está esperando.
GNU
grep
trata versões com escape de símbolos que têm significado especial em expressões regulares estendidas, mas não em BREs como símbolos especiais, mesmo em BREs: assim, em um BRE,\?
tem o mesmo significado que?
em um ERE. Portantogrep '<\?'
, corresponde a zero ou um<
, que corresponde a tudo (e destaca<
se você tiver a saída de cores ativada).O mesmo raciocínio aplicado a
sed
.