Como posso excluir todas as linhas em um arquivo de texto que tenha menos de 'x' letras OU números OU símbolos? Não posso usar awk 'length($0)>'
porque incluirá espaços.
Responder1
Supondo que você queira excluir linhas que contenham menos n
símbolos gráficos:
awk -v n=5 '{ line = $0; gsub("[^[:graph:]]", "") } length >= n { print line }'
Isso exclui todos os caracteres que não correspondem [[:graph:]]
. Se o comprimento da string restante for maior ou igual a n
, a linha (não modificada) será impressa.
O valor de n
é fornecido na linha de comando.
[[:graph:]]
é equivalente a [[:alnum:][:punct:]]
, que por sua vez é igual a [[:alpha:][:digit:][:punct:]]
. É aproximadamente o mesmo, [[:print:]]
mas não corresponde a espaços.
Em vez de [^[:graph:]]
, você poderia usar [[:blank:]]
para excluir todas as tabulações ou espaços.
Com sed
, seguindo o código acima awk
quase literalmente,
sed -e 'h; s/[^[:graph:]]//g' \
-e '/.\{5\}/!d; g'
ou, simplificado (contando apenas caracteres que não sejam espaços em branco),
sed -e 'h; s/[[:blank:]]//g' \
-e '/...../!d; g'
Isso primeiro salva a linha atual no espaço de espera com h
. Em seguida, ele exclui todos os caracteres não gráficos (ou caracteres em branco na segunda variação) na linha com s///g
. Se a linha contiver menos de 5 caracteres (altere para qualquer número desejado ou altere o número de pontos na segunda variação), a linha será excluída. Caso contrário, a linha armazenada é buscada no espaço de espera g
e (implicitamente) impressa.
Responder2
sed -e 's/[^[:space:][:cntrl:]]/&/20' -e t -e d < file
imprimiria as linhas file
que contêm pelo menos 20 caracteres sem espaço em branco e sem controle (veja também [[:graph:]]
ou [[:alnum:][:punct:]]
, não está claro quais caracteres você deseja incluir/excluir de sua descrição; tenha cuidado, pois em alguns sistemas, o caractere de espaço sem quebra está incluído graph
e não em space
).
A ideia é que ele tente substituir a 20ª ocorrência de um caractere que não seja espaço em branco/controle por ele mesmo ( &
) e ramificamos se essa substituição for bem-sucedida ( t
), ignorando assim a d
ação (excluir).
Com awk
você poderia fazer:
awk 'gsub(/[^[:space:][:cntrl:]]/, "&") >= 20' < file
Baseando-se no fato de que gsub()
retorna o número de substituições que fez.
Com grep
:
grep -E '^([[:space:][:cntrl:]]*[^[:space:][:cntrl:]]){20}' < file
( (.*[^[:space:][:cntrl:]]){20}
também funcionaria, mas seria mais caro).
Responder3
Isso excluirá as linhas que possuem 10 e menos de 10 caracteres:
sed -E '/^.{1,11}$/d' filename
OU
sed -r '/^.{1,11}$/d' filename
Se você quiser cortar espaços, você pode usar:
sed -E 's/^[[:space:]]*//g;s/[[:space:]]*$//g;/^.{1,11}$/d' filename
Se você quiser fazer a exclusão no local (diretamente dentro do arquivo), use-euopção com ele.
Responder4
Usando Raku (née Perl6)
raku -ne '.put if chars( S:g/\s// ) >= 10;' filename
ou
raku -ne '.put unless chars( S:g/\s// ) < 10;' filename
ou
raku -ne '.put unless chars( S:g/\W// ) < 10;' filename
ou
raku -ne '.put unless chars( S:g/<ws>// ) < 10;' filename
Resumidamente, em Raku/Perl6 o operador "S maiúsculo" S///
é usado para gerar uma string resultante desprovida de caracteres indesejados (por exemplo, espaços em branco), os caracteres da string resultante são contados com a chars
função, comparados com "n" (usando 10 como exemplo) e finalmente - se o booleano for satisfeito - .put
retornará a linha original intacta.
Nota 1: "S/// usa a mesma semântica que o operador s///, exceto que deixa a string original intacta e retorna a string resultante em vez de $/ ($/ ainda sendo definido com os mesmos valores de s///) ."
https://docs.raku.org/linguagem/regexes#S///_non-destructive_substitution
Nota 2: Em Raku/Perl6, modificadores de regex como :g
(para 'global') são conhecidos como advérbios e são (geralmente) colocados no início do operador S///
or s///
, logo após o S
or s
.
Nota 3: O .
ponto em Raku/Perl6 é usado para chamar um método na variável de tópico $_
, portanto a primeira 'palavra' do código .put
é essencialmente uma abreviação de $_.put
.
https://docs.raku.org/linguagem/5to6-nutshell#-%3E_Method_calls
Nota 4: Raku/Perl6 possui um conjunto muito mais restrito de sinalizadores de linha de comando. O -e
sinalizador ("executar") executa o código Raku/Perl6 na linha de comando. O -n
sinalizador executa o código Raku/Perl6 em linha, ou seja, em cada linha de um arquivo de entrada, uma linha por vez, retornando um resultado. As duas bandeiras podem ser combinadas em uma -ne
bandeira, mas independentemente disso, a -e
bandeira deve vir por último.
Links Perl_6:
https://docs.raku.org/linguagem/5to6-nutshell#Command-line_flags
https://github.com/rakudo/rakudo/wiki/Running-rakudo-from-the-command-line