Как использовать multiline в качестве разделителя групп в grep?

Ну, я нашел пару, которые действительно работают (NB, это - Ubuntu 11.04):

$ sh -c "bash -c 'a=1; echo a\$a \'"
a1
$ sh -c "bash -c 'a=1; echo a\$a;'"
a1

... и это кажется, пока первая одинарная кавычка не завершена, и доллара оставляют - это работает, независимо если заключительной одинарной кавычки оставляют или нет! Который озадачивает меня довольно немного тихий...

8
13.04.2017, 15:36
2 ответа

Ooooh I found it, I just need to use the $'' syntax instead instead $":

$ grep -C1 --group-separator=$'\n\n' 'hello' a
hello
this is me



something else
hello hello
bye

From man bash:

QUOTING

Words of the form $'string' are treated special. Слово расширяется до строки, при этом символы в обратном слэше заменяются как указанный в стандарте ANSI C. Последовательности эвакуации обратной косой черты, если присутствующие, расшифровываются следующим образом:

(...)
\n новая строка
11
27.01.2020, 20:11

Вот решение в Python, которое делает один проход над входным файлом, записывая выходные файлы, как он идет.

Возможность использования wc -l заключается в том, что предполагается, что каждая из записей имеет одинаковый размер. Это может быть правдой здесь, но решение ниже работает, даже когда это не так. В основном используется wc -c или количество байт в файле. В Python это делается через os.stat ()

Так вот как работает программа. Сначала вычисляются идеальные точки разделения как смещения байтов. Затем строки входного файла записываются в соответствующий выходной файл. Когда вы увидите, что вы превысили оптимальное следующее разделение пункта и вы находитесь на границе записи, закройте последний выходной файл и откройте следующий.

Программа оптимальна в этом смысле, она считывает байты входного файла один раз; Получение размера файла не требует чтения данных файла. Необходимое место хранения пропорционально размеру линии. Но Python или система, предположительно, имеют разумные файловые буферы для ускорения ввода-вывода.

Я добавил параметры для того, сколько файлов нужно разделить и каков размер записи на случай, если вы захотите изменить это в будущем.

И ясно, что это может быть переведено и на другие языки программирования.

Еще одна вещь, я не уверен, что Windows с ее crlf правильно обрабатывает длину линии, как в Unix-y системах. Если лен () выключен один здесь, я надеюсь, что это очевидно, как скорректировать программу.

#!/usr/bin/env python
import os

# Adjust these
filename = 'file.txt'
rec_size = 4
file_splits = 4

size = os.stat(filename).st_size
splits = [(i+1)*size/file_splits for i in range(file_splits)]
with open(filename, 'r') as fd:
    linecount = 0
    i = 0 # File split number
    out = open('file%d.txt' % i, 'w')
    offset = 0  # byte offset of where we are in the file: 0..size
    r = 0 # where we are in the record: 0..rec_size-1
    for line in fd:
        linecount += 1
        r = (r+1) % rec_size
        if offset + len(line) > splits[i] and r == 1 :
            out.close()
            i += 1
            out = open('file%d.txt' % i, 'w')
        out.write(line)
        offset += len(line)
    out.close()
    print("file %s has %d lines" % (filename, linecount))
-121--44103-

От man echo

Обычно можно различить флаг и последовательность, начинающуюся с дефиса, используя (двойной дефис). Поскольку с помощью эхо-команды флаги не поддерживаются, (двойной дефис) обрабатывается буквально.

Во втором примере

Примечание: если сообщение содержит побег последовательностей, оно должно быть помещено в кавычки. В противном случае оболочка интерпретирует\( обратная косая черта) как метасимвол и рассматривает\по-другому.

И действительно, на AIX:

~> header="
-------------------------------------
Name\tAge\tGender\tAddress
-------------------------------------
"

~> echo -e $header
-e ------------------------------------- Name   Age     Gender  Address -------------------------------------
~> echo "$header"

-------------------------------------
Name    Age     Gender  Address
-------------------------------------
-121--217153-

Я предлагаю использовать echo-e или printf с \\n для новой линии.

Пример (с эхо-е ):

$ grep -C1 --group-separator="$(echo -e line1\\n\\nline2)" 'hello' a
hello
this is me
line1
line2
something else
hello hello
bye

Пример (с printf ):

$ grep -C1 --group-separator="$(printf hello\\nfedorqui)" 'hello' a
hello
this is me
hello

fedorqui
something else
hello hello
bye

Одним из преимуществ является использование двойной кавычки . (следовательно, работа с переменным расширением и т.д.)

1
27.01.2020, 20:11

Теги

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