Usando o GNU-grep:
grep -Po '(".*?"|\S)+' file.txt
Eu tenho o seguinte texto que eu preciso substituir todo o espaço em branco com alimentação de linha, exceto qualquer coisa entre aspas.
ENTRADA
This is an example text with some spaces.
This should be 2nd line.
However the spaces between "quotes should not change".
last line
A saída deve ser semelhante a esta:
This
is
an
example
text
with
some
spaces.
This
should
be
2nd
line.
However
the
spaces
between
"quotes should not change".
last
line
Eu tentei usar o awk / sed / perl, mas não consegui colocar nada, exceto as aspas.
O texto citado não ultrapassará mais de uma linha.
Usando o GNU-grep:
grep -Po '(".*?"|\S)+' file.txt
EDITAR: Minha solução foi um exagero total. Eu não sei o que eu estava pensando. O problema pode ser resolvido por uma expressão regular extremamente simples. Consulte a solução enviada por JJoao .
A biblioteca Python shlex
quase faz isso pronto para uso. Aqui está um script de exemplo:
#!/usr/bin/env python2
# -*- coding: ascii -*-
"""tokens.py"""
import sys
import shlex
with open(sys.argv[1], 'r') as textfile:
text = ''.join(textfile.readlines())
for token in shlex.split(text, posix=False):
print(token)
Se seus dados estiverem no arquivo data.txt
(por exemplo), você poderá executá-lo assim:
python tokens.py data.txt
E aqui está a saída que produz:
This is an example text with some spaces. This should be 2nd line. However the spaces between "quotes should not change" . last line
Observe que ele coloca o período em uma linha separada. Isso ocorre porque termina os tokens nas cotações de fechamento. Como o exemplo que você deu não parece exigir cadeias de caracteres com múltiplas linhas ou caracteres com escape, provavelmente não é difícil criar seu próprio lexer. Aqui está o que eu criei:
#!/usr/bin/env python2
# -*- coding: ascii -*-
"""tokens.py"""
import sys
def tokenize(string):
"""Break a string into tokens using white-space as the only delimiter
while respecting double-quoted substrings and keeping the double-quote
characters in the resulting token."""
# List to store the resulting list of tokens
tokens = []
# List to store characters as we build the current token
token = []
# Flag to keep track of whether or not
# we're currently in a quoted substring
quoted = False
# Iterate through the string one character at a time
for character in string:
# If the character is a space then we either end the current
# token (if quoted is False) or add the space to the current
# token (if quoted is True)
if character == ' ':
if quoted:
token.append(character)
elif token:
tokens.append(''.join(token))
token = []
# A double-quote character is always added to the token
# It also toggles the 'quoted' flag
elif character == '"':
token.append(character)
if quoted:
quoted = False
else:
quoted = True
# All other characters are added to the token
else:
token.append(character)
# Whatever is left at the end becomes another token
if token:
tokens.append(''.join(token))
# Return the resulting list of strings
return(tokens)
if __name__=="__main__":
"""Read in text from a file and pring out the resulting tokens."""
with open(sys.argv[1], 'r') as textfile:
text = ''.join(textfile.readlines()).replace("\n", " ")
for token in tokenize(text):
print(token)
Isso produz exatamente os resultados que você pediu. Você provavelmente poderia implementar esse algoritmo em outro idioma (como o Perl) facilmente. Por acaso estou mais confortável com o Python.
Se linhas vazias do texto original puderem ser removidas:
sed -r 's/("[^"]*"[^ ]?)/\n\n/g' input.txt |
sed -r '/^"/!s/\s{1,}/\n/g' |
sed '/^$/d'
Se linhas vazias do texto original devem ser preservadas:
sed -r 's/("[^"]*"[^ ]?)/###\n\n###/g' input.txt |
sed -r '/^"/!s/\s{1,}/\n/g' |
sed '/###/d'
Entrada (complicada para o teste)
This is an "example text" with some spaces.
This should be 2nd line.
"However the spaces" between "quotes should not change".
"last line"
Saída
This
is
an
"example text"
with
some
spaces.
This
should
be
2nd
line.
"However the spaces"
between
"quotes should not change".
"last line"
Tags linux text-formatting