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
задан 23 March 2019 в 12:06

3 ответа

grep -v '^$' удалит пустые строки. Но что, если у нас есть пробелы или вкладки в некоторых строках? Например, я добавил 3 пробелов к частям Вашего текста, и если мы делаем cat -A мы будем видеть, что это показывает разделитель строки $, но это будет смещено.

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

Вторая строка там имеет 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 добавленными пробелами не стало. * показывает нуль или больше повторений символов, таким образом, шаблон ^[[:blank:]]*$ также подразумевает ^$ когда существует нулевой пробел или символы табуляции на строке. Таким образом, этот шаблон обрабатывает и действительно пустые и на вид пустые строки. Это также применяет точно то же к grep или sed, потому что мы используем основные regex выражения и [[:blank:]] один из классов символов POSIX, таким образом, это портативно.


Мы могли также сделать что-то вроде этого в Python, но без regex шаблонов:

$ 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 в комментариях, проблема может также произойти при использовании окончаний строки CRLF (используемый в текстовых файлах DOS/Windows). Легко видеть, использует ли файл окончания строки CRLF через cat -A, они будут отмечены как ^M. Например,

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

Одна вещь, которая могла быть сделана для составления возврата каретки, является этим:

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

Может быть более просто сначала использовать a dos2unix утилита, специально разработанная для преобразования файлов DOS в файлы Unix, и затем, использует sed и grep. См. ответ ByteCommander, который показывает пример того, как сделать это.

3
ответ дан 2 December 2019 в 01:42

По-видимому, Вы хотите удалить не только пустые строки, но также и строки только с пробельными символами. Для этого используйте:

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

sed выражение dэлиты каждая строка с любым числом (*) из пробельных символов (\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
ответ дан 2 December 2019 в 01:42

использовать

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
ответ дан 2 December 2019 в 01:42

Другие вопросы по тегам:

Похожие вопросы: