web-dev-qa-db-ja.com

sed '/ ^ $ / d'およびgrep -Ev '^ $'が空白行を削除できませんでした

Vscodeに複数の空白行があるそのようなファイルがあります

$ tail -n 20 draft3.py
            hi = len(a)  

        if lo < 0:
            raise ValueError('low must be non-negative')

        if lo == hi: 
            return None 

        mid = (lo + hi) // 2

        if x == a[mid]:
            return x
        if x > a[mid]:

            lo = mid + 1
            return self.bi_search(a, x, lo, hi)
        if x < a[mid]:

            hi = mid
            return self.bi_search(a, x, lo, hi)

空白行を削除するために複数の方法を試しました

`grep -v -e '^ $'が失敗しました

$ tail -n 20 draft3.py | grep -v -e '^$'
            hi = len(a)  
        if lo < 0:
            raise ValueError('low must be non-negative')
        if lo == hi: 
            return None 
        mid = (lo + hi) // 2

        if x == a[mid]:
            return x
        if x > a[mid]:

            lo = mid + 1
            return self.bi_search(a, x, lo, hi)
        if x < a[mid]:

            hi = mid
            return self.bi_search(a, x, lo, hi)

`grep -Ev" ^ $ "が失敗しました

$ tail -n 20 draft3.py | grep -Ev "^$" 
            hi = len(a)  
        if lo < 0:
            raise ValueError('low must be non-negative')
        if lo == hi: 
            return None 
        mid = (lo + hi) // 2

        if x == a[mid]:
            return x
        if x > a[mid]:

            lo = mid + 1
            return self.bi_search(a, x, lo, hi)
        if x < a[mid]:

            hi = mid
            return self.bi_search(a, x, lo, hi)

`sed '/ ^ $/d'が失敗しました

$ tail -n 20 draft3.py | sed '/^$/d'
            hi = len(a)  
        if lo < 0:
            raise ValueError('low must be non-negative')
        if lo == hi: 
            return None 
        mid = (lo + hi) // 2

        if x == a[mid]:
            return x
        if x > a[mid]:

            lo = mid + 1
            return self.bi_search(a, x, lo, hi)
        if x < a[mid]:

            hi = mid
            return self.bi_search(a, x, lo, hi)

どうしたの?どうすれば空白行を削除できますか?

2
Alice

おそらく、空の行だけでなく、空白文字のみの行も削除する必要があります。そのためには、以下を使用します。

sed '/^\s*$/d'   # or respectively
grep -v '^\s*$'

seddeletesすべての行を任意の番号(*)の空白文字(\s) 初期化。 grep -vは、式に一致しない行を出力します。

使用例

$ sed '/^\s*$/d' <draft3.py 
            hi = len(a)  
        if lo < 0:
            raise ValueError('low must be non-negative')
        if lo == hi: 
            return None 
        mid = (lo + hi) // 2
        if x == a[mid]:
            return x
        if x > a[mid]:
            lo = mid + 1
            return self.bi_search(a, x, lo, hi)
        if x < a[mid]:
            hi = mid
            return self.bi_search(a, x, lo, hi)
3
dessert

_grep -v '^$'_はempty行を削除します。しかし、いくつかの行にスペースまたはタブがある場合はどうなりますか?たとえば、テキストの一部に3つのスペースを追加した場合、_cat -A_を実行すると、行末記号_$_が表示されますが、オフセットされます。

_$
        mid = (lo + hi) // 2$
   $
        if x == a[mid]:$
            return x$
        if x > a[mid]:$
_

2行目には3つのスペースがありますが、最初の行にはありません。したがって、_[[:blank:]]_文字クラスを使用してそれらも考慮する必要があります。

_$ grep -v '^[[:blank:]]*$' text.txt
           hi = len(a)  
        if lo < 0:
            raise ValueError('low must be non-negative')
        if lo == hi: 
            return None 
        mid = (lo + hi) // 2
        if x == a[mid]:
            return x
        if x > a[mid]:
            lo = mid + 1
            return self.bi_search(a, x, lo, hi)
        if x < a[mid]:
            hi = mid
            return self.bi_search(a, x, lo, hi)
_

これで、3つのスペースが追加された行がなくなったことがわかります。 _*_は、文字の0回以上の繰り返しを意味します。したがって、パターンに_^[[:blank:]]*$_は、行に空白文字またはタブ文字がない場合、_^$_も意味します。したがって、このパターンは、真に空の行と一見空の行の両方を処理します。基本的な正規表現を使用しており、_[[:blank:]]_は POSIX文字クラス の1つであるため、grepまたはsedにもまったく同じように適用されます。だから、携帯可能です。


pythonでも次のようなことをすることができますが、正規表現パターンなしで:

_$ python3 -c 'import sys; print("\n".join([ l.rstrip() for l in sys.stdin if l.strip().split() ]))'  < text.txt
           hi = len(a)
        if lo < 0:
            raise ValueError('low must be non-negative')
        if lo == hi:
            return None
        mid = (lo + hi) // 2
        if x == a[mid]:
            return x
        if x > a[mid]:
            lo = mid + 1
            return self.bi_search(a, x, lo, hi)
        if x < a[mid]:
            hi = mid
            return self.bi_search(a, x, lo, hi)
_

なぜこれが機能するのですか?文字列の.split()は空白で分割され、空白以外のトークンを抽出するためです。行にスペースのみが含まれている場合、.split()の結果リストは空になります。


コメントのilkkachuで述べられているように、この問題はCRDOS行末(DOS/Windowsテキストファイルで使用)を使用した場合にも発生する可能性があります。ファイルが_cat -A_を介してCRLF行末を使用しているかどうかを簡単に確認できます。それらは_^M_としてマークされます。例えば、

_$ printf 'hello\n\r\nWorld\n   \r\ntest\n\nnewtest\n' | cat -A
hello$
^M$
World$
   ^M$
test$
$
newtest$
_

キャリッジリターンを説明するために実行できることの1つは次のとおりです。

_$ printf 'hello\n\r\nWorld\n   \ntest\n\nnewtest\n' | sed '/^[[:blank:]]*\r*$/d'
hello
World
test
newtest
_

最初にDOSファイルをUnixファイルに変換するために特別に設計された_dos2unix_ユーティリティを使用し、次にsedおよびgrepを使用する方が簡単な場合があります。その方法の例を示す ByteCommanderの回答 を参照してください。

3

使用する

Perl -p  -e 's/^[:blank:]*$//g' inputfile | sed '/^$/d' 

そしてあなたは

tail -n 20 draft3.py
            hi = len(a)
        if lo < 0:
            raise ValueError('low must be non-negative')
        if lo == hi:
            return None
        mid = (lo + hi) // 2
        if x == a[mid]:
            return x
        if x > a[mid]:
            lo = mid + 1
            return self.bi_search(a, x, lo, hi)
        if x < a[mid]:
            hi = mid
            return self.bi_search(a, x, lo, hi)

Sedでのみ

sed -r 's/^[[:space:]]*$//g' inputfile | sed '/^$/d'
0
aborruso