Как прочитать файл из /begin/ в /end/, если оба могут быть на одной строке

ansible_all_ipv4_addressesуже является массивом, поэтому вам не нужно splitего:

- copy:
    dest: /tmp/ips
    content: "{{ ansible_all_ipv4_addresses | join('\n') }}"

Это даст желаемый результат.

0
29.12.2020, 16:13
3 ответа

Вы можете использовать pcregrepрежим нескольких линий -:

$ pcregrep --include='\.h$' -rM '(?s)^\s*(\w+\s+)*int cacheflush\s*\(.*?;' glibc
glibc/sysdeps/unix/sysv/linux/mips/sys/cachectl.h:extern int cacheflush (void *__addr, const int __nbytes, const int __op) __THROW;
glibc/sysdeps/unix/sysv/linux/csky/sys/cachectl.h:extern int cacheflush (void *__addr, const int __nbytes,
                       const int __op) __THROW;
glibc/sysdeps/unix/sysv/linux/nios2/sys/cachectl.h:extern int cacheflush (void *__addr, const int __nbytes, const int __op) __THROW;

А с помощью PCRE вы получаете доступ к большинству расширенных операторов регулярных выражений Perl. Здесь мы используем:

  • \wи \sдля слов и пробелов.
  • (?s):позволяет флагу sдля .также совпадать с символами новой строки.
  • *?:не -жадная версия *. Таким образом, он соответствует первому вхождению ;, а не последнему, как в жадной версии.

Для получения подробной информации см. справочную страницу pcrepattern(3).

3
18.03.2021, 22:40

Я придумал (уродливое )решение:

  1. Считайте с /begin/по/^$/(пустую строку ), повторяя первую строку шаблона, чтобыsed(1)мог воздействовать на нее на последующем шаге.

  2. Используйте sed(1), чтобы найти от /begin/до /end/. Оставьте пустые строки на этом шаге, чтобы иметь возможность использоватьuniq(1)для правильного удаления на следующем шаге строк, которые мы повторили на шаге 1.

  3. Используйтеuniq(1)для удаления повторяющихся строк.

$ syscall=cacheflush;
$ return=int;
$ pattern="^[a-z ]*${return} ${syscall}[ ]*(";
$ find glibc/ -name '*.h' \
  |xargs sed -n -e "/${pattern}/p" -e "/${pattern}/,/^$/p" \
  |sed -n -e "/${pattern}/,/;/p" -e '/^$/p' \
  |uniq;
extern int cacheflush (void *__addr, int __nbytes, int __op) __THROW;

extern int cacheflush (void *__addr, const int __nbytes,
               const int __op) __THROW;

extern int cacheflush (void *__addr, const int __nbytes, const int __op) __THROW;

extern int cacheflush (void *__addr, const int __nbytes, const int __op) __THROW;

Пожалуйста, предложите более простое решение:)

0
18.03.2021, 22:40

Нет необходимости вызывать sedдважды, вы просто проверяете перед вводом диапазона, находятся ли начало/конец в одной строке.

$ find glibc/ -name '*.h' \
|xargs sed \
    -e "/${pattern}.*;\$/b"  \
    -e "/${pattern}/,/;\$/p" \
    -e 'd' ;

Обратите внимание, что будет хорошо, если вы ограничите утилиту findпоиском только обычных файлов, в противном случае вы можете увидеть предупреждения, когда sedработает с каталогом, имя которого заканчивается на.h

1
18.03.2021, 22:40

Теги

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