Eu gostaria de remover todos os espaços e tabulações iniciais e finais de cada linha em uma saída.
Existe uma ferramenta simples como trim
Eu poderia canalizar minha saída para?
Arquivo de exemplo:
test space at back test space at front TAB at end TAB at front sequence of some space in the middle some empty lines with differing TABS and spaces: test space at both ends
Comentários
- Para quem procura aqui uma solução para remover novas linhas, esse é um problema diferente. Por definição, uma nova linha cria uma nova linha de texto. Portanto, uma linha de texto não pode conter uma nova linha. A pergunta que você quer fazer é como remover uma nova linha do início ou final de uma string: stackoverflow.com/questions/369758 ou como remover espaços em branco linhas ou linhas que são apenas espaços em branco: serverfault.com/questions/252921
Resposta
awk "{$1=$1;print}"
ou mais curto:
awk "{$1=$1};1"
Cortaria à esquerda e espaço à direita ou caracteres de tabulação 1 e também sequências de compressão de tabulações e espaços em um único espaço.
Isso funciona porque quando você atribui algo a um dos campos , awk
reconstrói o registro inteiro (conforme impresso por print
) juntando todos os campos ($1
, …, $NF
) com OFS
(espaço por padrão).
1 (e possivelmente outro caractere em branco s dependendo da localidade e da awk
implementação)
Comentários
- Ponto e vírgula em o segundo exemplo é supérfluo. Pode usar:
awk '{$1=$1}1'
- @Brian, não, o
;
é necessário na sintaxe padrão do awk - Interessante … Nenhum ponto-e-vírgula é compatível com gawk, mawk e OS X ‘ s awk. (Pelo menos para minhas versões (1.2, 4.1.1 e 20070501, respectivamente)
- A única coisa que eu não ‘ gosto nessa abordagem é que você perder espaços repetidos dentro da linha. Por exemplo,
echo -e 'foo \t bar' | awk '{$1=$1};1'
-
echo ' hello ' | xargs
Resposta
O comando pode ser condensado desta forma se você estiver usando GNU sed
:
$ sed "s/^[ \t]*//;s/[ \t]*$//" < file
Exemplo
Aqui está o comando acima em ação.
$ echo -e " \t blahblah \t " | sed "s/^[ \t]*//;s/[ \t]*$//" blahblah
Você pode usar hexdump
para confirmar que o comando sed
está removendo os caracteres desejados corretamente.
$ echo -e " \t blahblah \t " | sed "s/^[ \t]*//;s/[ \t]*$//" | hexdump -C 00000000 62 6c 61 68 62 6c 61 68 0a |blahblah.| 00000009
Classes de caracteres
Você também pode usar nomes de classes de caracteres em vez de listar literalmente os conjuntos como este, [ \t]
:
$ sed "s/^[[:blank:]]*//;s/[[:blank:]]*$//" < file
Exemplo
$ echo -e " \t blahblah \t " | sed "s/^[[:blank:]]*//;s/[[:blank:]]*$//"
A maioria das ferramentas GNU que fazem uso de expressões regulares ssions (regex) suportam essas classes (aqui com seu equivalente na localidade C típica de um sistema baseado em ASCII (e somente lá)).
[[:alnum:]] - [A-Za-z0-9] Alphanumeric characters [[:alpha:]] - [A-Za-z] Alphabetic characters [[:blank:]] - [ \t] Space or tab characters only [[:cntrl:]] - [\x00-\x1F\x7F] Control characters [[:digit:]] - [0-9] Numeric characters [[:graph:]] - [!-~] Printable and visible characters [[:lower:]] - [a-z] Lower-case alphabetic characters [[:print:]] - [ -~] Printable (non-Control) characters [[:punct:]] - [!-/:-@[-`{-~] Punctuation characters [[:space:]] - [ \t\v\f\n\r] All whitespace chars [[:upper:]] - [A-Z] Upper-case alphabetic characters [[:xdigit:]] - [0-9a-fA-F] Hexadecimal digit characters
Usando estes em vez de conjuntos literais sempre parecem uma perda de espaço, mas se você está preocupado com o seu código ser portátil, ou ter que lidar com conjuntos de caracteres alternativos (pense internacional), então você provavelmente desejará usar os nomes das classes. .
Referências
Comentários
- Observe que
[[:space:]]
não é equivalente a[ \t]
no caso geral (unicode, etc).[[:space:]]
provavelmente será muito mais lento (já que existem muitos mais tipos de espaços em branco em Unicode do que apenas' '
e'\t'
). A mesma coisa para todos os outros. -
sed 's/^[ \t]*//'
não é portátil. Atualmente POSIX requer que remova uma sequência de espaço, barra invertida out
caracteres, e que ‘ seja o que GNUsed
também faz quandoPOSIXLY_CORRECT
está no ambiente. - E se eu quiser cortar caracteres de nova linha? ‘ \ n \ n texto \ n \ n ‘
- Gosto da solução sed por causa da falta de outros efeitos colaterais como na solução awk. A primeira variação não funcionou quando tentei no bash no OSX apenas agora, mas a versão da classe de personagem funciona:
sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//'
- @EugeneBiryukov veja meu comentário sobre a postagem original
Resposta
xargs sem argumentos fazem isso.
Exemplo:
trimmed_string=$(echo "no_trimmed_string" | xargs)
Comentários
- Isso também contrai vários espaços dentro uma linha, que não foi solicitada na questão
- @roaima – true mas a resposta aceita também espreme espaços (o que não foi solicitado na questão). Acho que o verdadeiro problema aqui é que
xargs
não será entregue se a entrada contiver barras invertidas e aspas simples. - @don_crissti que não ‘ t significa que a resposta aceita responde corretamente à pergunta conforme feita. Mas neste caso aqui não foi ‘ t sinalizado como uma advertência, enquanto na resposta aceita era. Eu ‘ espero destacar o fato caso seja ‘ relevante para um futuro leitor.
- Também quebras em aspas simples, aspas duplas, caracteres de barra invertida. Ele também executa uma ou mais invocações
echo
. Algumas implementações de eco também processarão opções e / ou barras invertidas … Isso também funciona apenas para entrada de linha única.
Resposta
Conforme sugerido por Stéphane Chazelas na resposta aceita, agora você pode
criar um script /usr/local/bin/trim
:
#!/bin/bash awk "{$1=$1};1"
e conceda a esse arquivo direitos executáveis:
chmod +x /usr/local/bin/trim
Agora você pode passar todos os resultados para trim
por exemplo:
cat file | trim
(para os comentários abaixo: eu usei isso antes: while read i; do echo "$i"; done
que também funciona bem, mas tem menos desempenho)
Comentários
- Boa sorte se seu arquivo for enorme e / ou contiver barras invertidas.
- @don_crissti: você poderia comentar um pouco mais ?, qual solução seria ser mais adequado para arquivos grandes, e como eu poderia modificar minha solução se o arquivo continha barras invertidas?
- Você ‘ terá que usar
while read -r line
para preservar as barras invertidas e mesmo assim … . Com relação a arquivos / velocidade enormes, você escolheu a pior solução. Eu não ‘ não acho que ‘ haja algo pior por aí. Veja as respostas em Por que usar um loop de shell para processar texto é uma prática inadequada? , incluindo meu comentário na última resposta, onde adicionei um link para um benchmark de velocidade. Assed
respostas aqui são perfeitamente boas na IMO e muito melhores do queread
. - Você também pode adicionar um alias em / etc / profile (ou seu ~ / .bashrc ou ~ / .zshrc etc …) alias trim = ” awk ‘ { \ $ 1 = \ $ 1}; 1 ‘ ”
- Não há necessidade de
bash
, você pode torná-lo#! /usr/bin/awk -f
{$1=$1};1
. (cuidado com os nomes de arquivo que contêm=
caracteres)
Resposta
Se você armazenar linhas como variáveis, poderá usar o bash para fazer o trabalho:
remova o espaço em branco inicial de uma string:
shopt -s extglob echo ${text##+([[:space:]])}
remover espaços em branco finais de uma string:
shopt -s extglob echo ${text%%+([[:space:]])}
remover todos os espaços em branco de uma string:
echo ${text//[[:space:]]}
Comentários
- Remover todos os espaços em branco de uma string não é o mesmo que remover espaços à esquerda e à direita (como na pergunta).
- De longe a melhor solução – requer apenas bash embutidos e nenhum bifurcação de processo externo.
- Legal. Os scripts são executados MUITO mais rápido se não ‘ não precisarem puxar programas externos (como awk ou sed). Isso funciona com versões ” modernas ” (93u +) de ksh, também.
Resposta
sed -e "s/^[[:space:]]*//" -e "s/[[:space:]]*$//"
Se você “estiver lendo uma linha em uma variável shell, read
já faz isso a menos que seja instruído de outra forma .
Comentários
- +1 para
read
. Então, se você redirecionar para enquanto lê, funciona:cat file | while read i; do echo $i; done
- @rubo exceto que no seu exemplo, a variável não citada também é reprocessada pelo shell. Use
echo "$i"
para ver o verdadeiro efeito deread
Resposta
Para remover todos os espaços iniciais e finais de uma determinada linha, graças a uma ferramenta “piped”, posso identificar 3 diferentes caminhos que não são completamente equivalentes. Essas diferenças dizem respeito aos espaços entre as palavras da linha de entrada. Dependendo do b esperado ehaviour, você fará sua escolha.
Exemplos
Para explicar as diferenças, vamos considerar esta linha de entrada fictícia:
" \t A \tB\tC \t "
tr
$ echo -e " \t A \tB\tC \t " | tr -d "[:blank:]" ABC
tr
é realmente um comando simples. Nesse caso, ele exclui qualquer espaço ou caractere de tabulação.
awk
$ echo -e " \t A \tB\tC \t " | awk "{$1=$1};1" A B C
awk
exclui os espaços iniciais e finais e reduz para um único espaço todos os espaços entre as palavras.
sed
$ echo -e " \t A \tB\tC \t " | sed "s/^[ \t]*//;s/[ \t]*$//" A B C
Neste caso, sed
exclui espaços iniciais e finais sem tocar em nenhum espaço entre as palavras.
Observação:
No caso de uma palavra por linha, tr
faz o trabalho.
Comentários
- Nada disso corta novas linhas à direita / à esquerda
- +1 para uma lista de soluções com sua saída (às vezes inesperada).
- @ user61382 já é tarde, mas veja meu comentário na postagem original.
- @highmaintenance: use
[:space:]
, em vez de [: blank:], para o comandotr
, como:... | tr -d [:space:]
, para remover novas linhas também. (consulte:man tr
)
Resposta
sed é um ótima ferramenta para isso:
# substitute ("s/") sed "s/^[[:blank:]]*//; # parts of lines that start ("^") with a space/tab s/[[:blank:]]*$//" # or end ("$") with a space/tab # with nothing (/)
Você pode usá-lo para o seu caso seja para encurtar o texto, por exemplo,
<file sed -e "s/^[[...
ou agindo de acordo “inline” se o seu sed
for o GNU:
sed -i "s/..." file
mas alterar a fonte desta forma é “perigoso”, pois pode ser irrecuperável quando não funciona bem (ou mesmo quando funciona!), então faça backup primeiro (ou use -i.bak
que também tem o benefício de ser portátil para alguns sed
s) BSD!
Resposta
Uma resposta que você pode entender rapidamente:
#!/usr/bin/env python3 import sys for line in sys.stdin: print(line.strip())
Bônus: substituir str.strip([chars])
com caracteres arbitrários para cortar ou usar .lstrip()
ou .rstrip()
conforme necessário.
Como rubo77 “sa nswer , salve como script /usr/local/bin/trim
e conceda permissões com chmod +x
.
Resposta
Se a string que se está tentando cortar for curta e contínua / contígua, pode-se simplesmente passá-la como um parâmetro a qualquer função bash:
trim(){ echo $@ } a=" some random string " echo ">>`trim $a`<<" Output >>some random string<<
Resposta
Escrevi esta função shell usando awk
awkcliptor(){ awk -e "BEGIN{ RS="^$" } {gsub(/^[\n\t ]*|[\n\t ]*$/,"");print ;exit}" "$1" ; }
BEGIN{ RS="^$" }
:
no início antes de começar a analisar definir registro
separador para nenhum isto é, tratar toda a entrada como
um único registro
gsub(this,that)
:
substitua esta expressão regular por aquela string
/^[\n\t ]*|[\n\t ]*$/
:
dessa string captura qualquer espaço de nova linha e classe de tabulação
ou poste espaço de nova linha e classe de tabulação e substitua-os por
string vazia
print;exit
: em seguida, imprima e saia
"$1"
:
e passe o primeiro argumento da função para be
process by awk
como usar:
copie o código acima, cole no shell e entre para
definir a função.
então você pode usar awkcliptor como um comando com o primeiro argumento como o arquivo de entrada
exemplo de uso:
echo " ggggg " > a_file awkcliptor a_file
saída:
ggggg
ou
echo -e "\n ggggg \n\n "|awkcliptor
saída:
ggggg
Comentários
- Você pode explicar a diferença apenas para
awk '{$1=$1};1'
?
Resposta
Para aqueles de nós sem espaço suficiente no cérebro para lembrar a sintaxe obscura do sed, basta inverter a string , corte o primeiro campo com um delimitador de espaço e inverta-o novamente.
cat file | rev | cut -d" " -f1 | rev
Comentários
- Isso só funciona se não houver mais de um espaço antes de cada linha e não mais de uma palavra em qualquer linha.
Resposta
trimpy () { python3 -c "import sys for line in sys.stdin: print(line.strip())" } trimsed () { gsed -e "s/^[[:space:]]*//" -e "s/[[:space:]]*$//" } trimzsh () { local out="$(</dev/stdin)" [[ "$out" =~ "^\s*(.*\S)\s*$" ]] && out="$match[1]" || out="" print -nr -- "$out" } # example usage echo " hi " | trimpy
Bônus: substitua str.strip([chars])
por caracteres arbitrários para cortar ou usar ou .rstrip()
conforme necessário.
Resposta
O comando de tradução funcionaria
cat file | tr -d [:blank:]
Comentários
- Este comando não está correto porque remove todos os espaços do arquivo, não apenas os espaços em branco iniciais / finais.
- @BrianRedbeard Você está correto. Esta ainda é uma resposta útil para uma string monolítica, sem espaços.
Resposta
para exemplo de bash:
alias trim="awk "{\$1=\$1};1""
uso:
echo -e " hello\t\tkitty " | trim | hexdump -C
resultado:
00000000 68 65 6c 6c 6f 20 6b 69 74 74 79 0a |hello kitty.| 0000000c
Comentários
- A
awk '{$1=$1};1'
resposta foi dada há muito tempo. A ideia de transformar isso em um pseudônimo foi sugerida em um comentário quase tão antigo. Sim, você tem permissão para pegar o comentário de outra pessoa e transformá-lo em uma resposta. Mas, se você fizer isso, você deve dar crédito às pessoas que postaram a ideia antes de você. E esta é uma extensão tão trivial da resposta aceita que realmente não vale a pena se preocupar. - A ideia era fazer um alias. Não ‘ nunca vi essa resposta antes.
- e a segunda coisa da pilha: ” Obrigado pelo feedback! Os votos lançados por pessoas com menos de 15 de reputação são registrados, mas não alteram a pontuação da postagem exibida publicamente. ”