sed находит и заменяет, но только в текстовых блоках между соответствующими шаблонами - PullRequest
0 голосов
/ 24 января 2020

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

Файл дампа имеет следующую структуру:

COPY public.my_target_table (id, name, content_type_id, codename) FROM stdin;
1   Can add association 1   add_association
2   Can change association  1   change_association
<..................>


COPY public.table_2 (id, name, content_type_id, codename) FROM stdin;
1   Can add association 1   add_association
2   Can change association  1   change_association

Значения табуляции разделены. Моя первоначальная идея состояла в том, чтобы sed найти / заменить между соответствующими индексами, но я понял, что мне нужно будет сделать это только для одной конкретной таблицы c (в противном случае я стираю данные из всех таблиц по этому индексу).

Есть ли способ указать sed действовать только после того, как он прошел строку my_target_table, и отключить, когда достигнет следующей пустой строки?

изменить для ясности

Используя приведенный выше пример, мы хотим вывести:

COPY public.my_target_table (id, name, content_type_id, codename) FROM stdin;
1   \N  1   add_association
2   \N  1   change_association
<..................>


COPY public.table_2 (id, name, content_type_id, codename) FROM stdin;
1   Can add association 1   add_association
2   Can change association  1   change_association

... при условии, что память у меня правильная, а \N означает ноль. В идеале ответ может быть расширен до любой целевой таблицы и индекса столбца (или даже лучше, целевой таблицы и имени столбца :)). Кроме того, я не ограничен sed - я слышал, awk может быть полезным инструментом здесь?

Ответы [ 2 ]

1 голос
/ 24 января 2020

С sed как насчет:

tab=$'\t'
sed "
/my_target_table/ { n
:l
s/^\\([^$tab]*$tab\\)[^$tab]*/\\1\\\\N/
n
/[^[:blank:]]/b l
}" file

Вывод для предоставленного образца:

COPY public.my_target_table (id, name, content_type_id, codename) FROM stdin;
1       \N      1       add_association
2       \N      1       change_association
<..................>


COPY public.table_2 (id, name, content_type_id, codename) FROM stdin;
1       Can add association     1       add_association
2       Can change association  1       change_association
  • Учитывая posix sed, который не поддерживает \t примечание, назначьте переменную оболочки tab символу табуляции в начале.
  • если шаблон /my_target_table/ найден, выполните команду sed в диапазоне от { до }.
  • :l создает метку для команды b.
  • s/^\\([^$tab]*$tab\\)[^$tab]*/\\1\\\\N/ заменяет второе поле строки, разделенное табуляцией, строкой \N.
  • n print Извлеките текущее пространство шаблона и прочитайте следующую строку.
  • /[^[:blank:]]/b l возвращается к метке l, пока строка не станет пустой.

Надеюсь, это поможет.

0 голосов
/ 24 января 2020

Возможно, есть более простой способ, но он работает:

BEGIN { OFS=FS="\t" }
/my_target_table/ { s = 1; print; next }
/^$/ { s = 0 }
(NF>1) && (s==1) { $2 = "<redacted>" }
1

awk -f script.awk sql_dump

COPY public.my_target_table (id, name, content_type_id, codename) FROM stdin;
1   <redacted>  1   add_association
2   <redacted>  1   change_association
<..................>


COPY public.table_2 (id, name, content_type_id, codename) FROM stdin;
1   Can add association 1   add_association
2   Can change association  1   change_association
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...