파일에서 여러 개의 빈 줄을 제거하는 방법? (대부분). 몇 가지 옵션으로 직접

나는 보통 텍스트를 사용하여 메모를 작성하는 데 사용하는 텍스트 파일이 있습니다 cat >> file. 때때로 나는 빈 줄이나 두 줄을 사용하여 (새 줄 문자 만 반환) 새로운 주제 / 생각을 지정합니다. 각 세션이 끝나면 Ctrl+로 파일을 닫기 전에 D일반적으로 세션을 분리하기 위해 많은 (5-10) 개의 빈 줄 (return-key)을 추가합니다.

이것은 분명히 영리하지는 않지만이 목적으로 저에게 효과적입니다. 내가 최종 최대 그러나 많은 불필요한 빈 줄이 많은, 내가 제거하는 방법을 찾고 있어요 그래서 여분의 라인 (대부분). 몇 가지 옵션으로 직접 사용할 수있는 Linux 명령 (cut, paste, grep, …?)이 있습니까? 또는 sed, awk 또는 perl에 대한 아이디어가 있습니까? C ++로 무언가를 작성하면 (실제로 스스로 할 수 있음) 과잉처럼 보입니다.

사례 # 1 : 필요한 것은 연속 된 빈 줄을 두 개 이상 제거하고 두 개의 빈 줄로 바꾸는 스크립트 / 명령입니다. 하나 이상의 줄을 제거하거나 (2 개 이상) 여러 개의 빈 줄을 하나의 빈 줄로 바꾸는 것도 좋은 방법입니다.

사례 # 2 : 두 줄의 텍스트 사이 에서 하나의 빈 줄을 제거하는 스크립트 / 명령을 사용할 수도 있지만 여러 줄을 그대로 둡니다 (빈 줄 중 하나를 제거해도됩니다).



답변

사례 1 :

awk '!NF {if (++n <= 2) print; next}; {n=0;print}'

사례 2 :

awk '!NF {s = s $0 "\n"; n++; next}
     {if (n>1) printf "%s", s; n=0; s=""; print}
     END {if (n>1) printf "%s", s}'

답변

uniq빈 줄의 여러 인스턴스를 하나의 빈 줄로 축소하는 데 사용할 수 있지만 텍스트가 같은 줄과 서로 아래 인 경우 줄이 축소됩니다.


답변

사례 1 :

perl -i -ane '$n=(@F==0) ? $n+1 : 0; print if $n<=2'

사례 2 :

perl -i -ane '$n=(@F==0) ? $n+1 : 0; print $n==2 ? "\n$_" : $n==1 ? "" : $_ '

답변

GNU sed를 사용하여 사례 1을 다음과 같이 해결할 수 있습니다.

sed -r ':a; /^\s*$/ {N;ba}; s/( *\n *){2,}/\n\n/'

즉, 패턴 공간에서 빈 줄을 수집하고 3 개 이상의 줄이 있으면 두 줄로 줄이십시오.

사례 # 2에서와 같이 단일 공백 ​​행을 결합하려면 다음과 같이 수행하십시오.

sed -r '/^ *\S/!b; N; /\n *$/!b; N; /\S *$/!b; s/\n *\n/\n/'

또는 주석이 달린 형식으로 :

sed -r '
  /^ *\S/!b        # non-empty line
  N                #
  /\n *$/!b        # followed by empty line
  N                #
  /\S *$/!b        # non-empty line
  s/\n *\n/\n/     # remove the empty line
'

답변

이 솔루션은 파일의 마지막 빈 줄도 처리합니다.

sed -r -n '
  /^ *$/!{p;b}  # non-blank line - print and next cycle
  h             # blank line - save it in hold space
  :loop
  $b end        # last line - go to end
  n             # read next line in pattern space
  /^ *$/b loop  # blank line - loop to next one
  :end          # pattern space has non-blank line or last blank line
  /^ *$/{p;b}   # last blank line: print and exit
  H;x;p         # non-blank line: print hold + pattern space and next cycle
'

답변

“uniq”를 사용하기위한 Anthon 의 제안에 따라 …

선행, 후행 및 빈 줄을 제거합니다.

# Get large random string.
rand_str=; while [[ ${#rand_str} -lt 40 ]]; do rand_str=$rand_str$RANDOM; done

# Add extra lines at beginning and end of stdin.
(echo $rand_str; cat; echo $rand_str) |

# Convert empty lines to random strings.
sed "s/^$/$rand_str/" |

# Remove duplicate lines.
uniq |

# Remove first and last line.
sed '1d;$d' |

# Convert random strings to empty lines.
sed "s/$rand_str//"

하나의 긴 줄에서 :

(rand_str=; while [[ ${#rand_str} -lt 40 ]]; do rand_str=$rand_str$RANDOM; done; (echo $rand_str; cat; echo $rand_str) | sed "s/^$/$rand_str/" | uniq | sed '1d;$d' | sed "s/$rand_str//")

또는 “cat -s”를 사용하십시오.

더 효율적인 현재 쉘 컨텍스트 를 유지하기 위해 괄호에서 중괄호로 전환했습니다 . 중괄호에는 마지막 명령 후 세미콜론이 필요하며 분리 할 공간이 필요합니다.

# Add extra blank lines at beginning and end.
# These will be removed in final step.
{ echo; cat; echo; } |

# Replace multiple blank lines with a single blank line.
cat -s |

# Remove first and last line.
sed '1d;$d'

한 줄로.

{ { echo; cat; echo; } | cat -s | sed '1d;$d'; }

답변

게시 된 솔루션은 나에게 조금 비밀스러워 보였다. 다음은 Python 3.6의 솔루션입니다.

#!/usr/bin/env python3

from pathlib import Path
import sys
import fileinput


def remove_multiple_blank_lines_from_file(path, strip_right=True):
    non_blank_lines_out_of_two_last_lines = [True, True]
    for line in fileinput.input(str(path), inplace=True):
        non_blank_lines_out_of_two_last_lines.pop(0)
        non_blank_lines_out_of_two_last_lines.append(bool(line.strip()))
        if sum(non_blank_lines_out_of_two_last_lines) > 0:
            line_to_write = line.rstrip() + '\n' if strip_right else line
            sys.stdout.write(line_to_write)


def remove_multiple_blank_lines_by_glob(rglob='*', path=Path('.'), strip_right=True):
    for p in path.rglob(rglob):
        if p.is_file():
            try:
                remove_multiple_blank_lines_from_file(p, strip_right=strip_right)
            except Exception as e:
                print(f"File '{p}' was not processed due the error: {e}")


if __name__ == '__main__':
    remove_multiple_blank_lines_by_glob(sys.argv[1], Path(sys.argv[2]), next(iter(sys.argv[3:]), None) == '--strip-right')

다음과 같이 인터프리터에서 함수를 호출하거나 쉘에서 실행할 수 있습니다.

$ ./remove_multiple_lines.py '*' /tmp/ --strip-right