검색 및 바꾸기(따옴표 제외)

검색 및 바꾸기(따옴표 제외)

다음 텍스트가 있고 모든 공백(따옴표 안의 공백 제외)을 개행 문자로 바꿔야 합니다.

입력하다

This is an example text with    some      spaces.
This should be 2nd line.
However the spaces between "quotes    should not    change".
last line

출력은 다음과 같아야 합니다.

This
is
an
example
text
with    
some
spaces.
This
should
be
2nd
line.
However
the
spaces
between
"quotes    should not    change".
last
line

awk/sed/perl을 사용해 보았지만 따옴표를 제외하고 어디에 넣어야 할지 알 수 없었습니다.

인용된 텍스트는 한 줄을 초과하지 않습니다.

답변1

편집하다:내 솔루션은 완전히 과잉이었습니다. 내가 무슨 생각을 했는지 모르겠어요. 이 문제는 매우 간단한 정규식으로 해결할 수 있습니다. 바라보다해결책에 의해 제출 된조아오.


파이썬 shlex라이브러리거의이것은 기본적으로 작동합니다. 다음은 예제 스크립트입니다:

#!/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)

예를 들어 데이터가 파일에 있는 경우 data.txt다음과 같이 실행할 수 있습니다.

python tokens.py data.txt

이것이 생성하는 출력은 다음과 같습니다.

이것
하나
텍스트
그리고
일부
공간.
이것
~해야 한다
2위
철사.
하지만
이것
공간
~ 사이
"인용문은 바뀌면 안 된다"
.
마지막
철사

마침표는 별도의 줄에 표시됩니다. 이는 닫는 따옴표로 태그를 끝내기 때문입니다. 당신이 제시한 예에는 여러 줄의 문자열이나 이스케이프 문자가 필요하지 않은 것 같으므로 자신만의 작은 어휘분석기를 굴리는 것이 그리 어렵지 않을 수도 있습니다. 이것이 내가 생각해낸 것입니다:

#!/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)

그러면 요청한 결과가 정확히 생성됩니다. Perl과 같은 다른 언어로 이 알고리즘을 쉽게 구현할 수 있습니다. 나는 단지 Python을 선호합니다.

답변2

GNU-grep을 사용하세요:

grep -Po '(".*?"|\S)+' file.txt

답변3

원본 텍스트에서 빈 줄을 제거할 수 있는 경우:

sed -r 's/("[^"]*"[^ ]?)/\n\1\n/g' input.txt |
sed -r '/^"/!s/\s{1,}/\n/g' |
sed '/^$/d'

원본 텍스트의 빈 줄을 유지해야 하는 경우:

sed -r 's/("[^"]*"[^ ]?)/###\n\1\n###/g' input.txt |
sed -r '/^"/!s/\s{1,}/\n/g' |
sed '/###/d'

입력하다(테스트가 더 복잡합니다.)

This is an "example text" with    some      spaces.
This should be 2nd line.
"However the spaces" between "quotes    should not    change".
"last line"

산출

This
is
an
"example text"
with
some
spaces.
This
should
be
2nd
line.
"However the spaces"
between
"quotes    should not    change".
"last line"

관련 정보