Suponha que meu arquivo se pareça com isto:
foo bar
foo bar bar
foo foo bar foo
O que eu quero fazer é excluir todos os foo
que são seguidos por um bar
(ou seja, há apenas espaços em branco entre eles), sem alterar nenhum espaço em branco. Abaixo, substituí todos os caracteres que devem ser excluídos por sublinhados para deixar isso claro:
___ bar
___ bar bar
foo ___ bar foo
O comando deve resultar no seguinte arquivo:
bar
bar bar
foo bar foo
Como eu poderia conseguir isso com sed ou awk?
OK, eu descobri como fazer isso. O comando para fazer isso com sed seria:
Com qualquer coisa que suporte expressões regulares compatíveis com perl (PCRE), você pode usar uma previsão positiva:
(?=)
é uma " afirmação de antecipação positiva de largura zero ".Ele precisa corresponder para que todo o RE corresponda, mas não inclui o que corresponde, portanto, você não precisa capturar e reinserir o texto correspondente.
Há também lookahead negativo e lookbehinds positivo e negativo, todos chamados coletivamente de "lookarounds".
Usando Raku (anteriormente conhecido como Perl_6)
As respostas acima são codificadas em Raku, um membro da família Perl de linguagens de programação. As vantagens do Raku incluem suporte integrado a Unicode de alto nível, bem como uma implementação Regex robusta/refinada. Acima, Raku Regexes são tolerantes a espaço em branco no domínio de reconhecimento (metade esquerda de
s///
), então os átomos Regex podem ser espalhados (e alinhados). Além disso, todos os modificadores Regex, como:global
(ou:g
) movem-se para a cabeça dos///
operador em Raku. Como Perl, o sinalizador global ou "advérbio" permite mais de uma correspondência por linha.A primeira resposta é uma tradução aproximada da excelente resposta Perl(5) de @jcaron. Observe que no Raku, as previsões positivas são escritas
<?before ... >
.<(
A segunda resposta usa os marcadores de captura de Raku)>
, para que, após a correspondência dos três átomos, apenasfoo
seja retido na captura (e excluído na substituição).Ambas as respostas mudam especificamente
foo
antesbar
, com apenas espaços em branco entre elas. Este é um ponto importante: dada a frase "my-valentine, my bloody valentine", o código Rakus:g/my <?before \s* valentine> //
removerá o primeiro "my" (porque "my- is_before -valentine"), mas o segundo "my" permanecerá intocado.https://docs.raku.org/language/regexes
https://raku.org