Como aparo os espaços em branco à esquerda e à direita de cada linha de alguma saída?

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 ou t caracteres, e que ‘ seja o que GNU sed também faz quando POSIXLY_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. As sed respostas aqui são perfeitamente boas na IMO e muito melhores do que read.
  • 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 de read

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 comando tr, 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. ”

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *