Вопрос или проблема
Я хочу использовать sed
, чтобы искать разрывы строк, которые не предшествуют }
.
Регулярное выражение для идентификации этих случаев: [^}]$
. Что я хочу сказать: если строка заканчивается без }
, удалите новую строку. Любая строка должна заканчиваться }
перед новой строкой.
Как это сделать с помощью sed
для их удаления?
ИЗМЕНЕНИЕ:
Пример:
{'Date': 'Fri, 19 Apr 2019 07:23:14 GMT', 'Server': 'Apache', 'Vary': 'Qualys-Scan', 'Strict-Transport-Security': 'max-age=31536000;includeSubDomains;preload', 'Set-Cookie': 'ASP.NET_SessionId=ivoa5bhet0s2ygkylmimvkie; path=/; secure; HttpOnly;SameSite=strict, SC_ANALYTICS_GLOBAL_COOKIE=12f133ea; expires=Thu, 19-Apr-2029 07:23:14 GMT; path=/; secure; HttpOnly;SameSite=strict, SC_ANALYTICS_SESSION_COOKIE=336B5|1|ivoa5; path=/; secure; HttpOnly;SameSite=strict, incap_ses_885_270026=cDp/VlO1AHgshF9F6SZID==; path=/; Domain=.zurich.co.uk, ___utmvm=dlNaoEsuXSO; path=/; Max-Age=900, ___utmvay=nWJx01KvGT; path=/; Max-Age=900, ___utm=JZy
XEtOwalQ: PtR; path=/; Max-Age=900', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block', 'Cache-Control': 'private', 'Content-Type': 'text/html; charset=utf-8', 'Keep-Alive': 'timeout=5, max=10', 'Connection': 'Keep-Alive', 'X-Iinfo': '8-3925806-3807 NNNN CT(73 151 0) RT(155583 5) q(0 0 3 0) r(6 6) U5', 'X-CDN': 'Incapsula', 'Content-Encoding': 'gzip', 'Transfer-Encoding': 'chunked'}
Когда я применил ваш скрипт, он объединил строки. Однако новая строка начинается с tab
. Как также удалить пробелы, если новая строка начинается с пробелов?
Вы можете использовать следующее, чтобы объединить строки, где предыдущая строка не заканчивается на }
:
sed -e :a -e '/}$/!N; s/\n//; ta'
Это по сути вариант 39. Присоедините строку к следующей, если она заканчивается обратной косой чертой “\” из Sed One-Liners Explained, Part I: File Spacing, Numbering and Text Conversion and Substitution, заменяя условие “заканчивается обратной косой чертой” на “не заканчивается правой скобкой”.
Например, дано
$ cat > input
foo bar
baz}
foo bar baz}
затем
$ sed -e :a -e '/}$/!N; s/\n//; ta' input
foo barbaz}
foo bar baz}
Если вы хотите также удалить любые ведущие горизонтальные пробелы в начале объединенной строки, вы можете изменить s/\n//
на s/\n[[:blank:]]*//
Тестирование на вашем примере (после преобразования ведущих пробелов в табуляции):
$ cat example
{'Date': 'Fri, 19 Apr 2019 07:23:14 GMT', 'Server': 'Apache', 'Vary': 'Qualys-Scan', 'Strict-Transport-Security': 'max-age=31536000;includeSubDomains;preload', 'Set-Cookie': 'ASP.NET_SessionId=ivoa5bhet0s2ygkylmimvkie; path=/; secure; HttpOnly;SameSite=strict, SC_ANALYTICS_GLOBAL_COOKIE=12f133ea5080403692b4ce458fd1a540; expires=Thu, 19-Apr-2029 07:23:14 GMT; path=/; secure; HttpOnly;SameSite=strict, SC_ANALYTICS_SESSION_COOKIE=336B597E7A534D6393C57DF11E047484|1|ivoa5bhet0s2ygkylmimvkie; path=/; secure; HttpOnly;SameSite=strict, incap_ses_885_270026=cDp/VlO1AHgshF9F6SZIDGJ3uVwAAAAAg7DwpecyehBCyhXgoYO5GA==; path=/; Domain=.zurich.co.uk, ___utmvmykuNyVY=dlNaoEsuXSO; path=/; Max-Age=900, ___utmvaykuNyVY=nWJx01KvGT; path=/; Max-Age=900, ___utmvbykuNyVY=JZy
XEtOwalQ: PtR; path=/; Max-Age=900', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block', 'Cache-Control': 'private', 'Content-Type': 'text/html; charset=utf-8', 'Keep-Alive': 'timeout=5, max=10', 'Connection': 'Keep-Alive', 'X-Iinfo': '8-3925806-3925807 NNNN CT(73 151 0) RT(1555658593583 5) q(0 0 3 0) r(6 6) U5', 'X-CDN': 'Incapsula', 'Content-Encoding': 'gzip', 'Transfer-Encoding': 'chunked'}
$ sed -e :a -e '/}$/!N; s/\n[[:blank:]]*//; ta' example
{'Date': 'Fri, 19 Apr 2019 07:23:14 GMT', 'Server': 'Apache', 'Vary': 'Qualys-Scan', 'Strict-Transport-Security': 'max-age=31536000;includeSubDomains;preload', 'Set-Cookie': 'ASP.NET_SessionId=ivoa5bhet0s2ygkylmimvkie; path=/; secure; HttpOnly;SameSite=strict, SC_ANALYTICS_GLOBAL_COOKIE=12f133ea5080403692b4ce458fd1a540; expires=Thu, 19-Apr-2029 07:23:14 GMT; path=/; secure; HttpOnly;SameSite=strict, SC_ANALYTICS_SESSION_COOKIE=336B597E7A534D6393C57DF11E047484|1|ivoa5bhet0s2ygkylmimvkie; path=/; secure; HttpOnly;SameSite=strict, incap_ses_885_270026=cDp/VlO1AHgshF9F6SZIDGJ3uVwAAAAAg7DwpecyehBCyhXgoYO5GA==; path=/; Domain=.zurich.co.uk, ___utmvmykuNyVY=dlNaoEsuXSO; path=/; Max-Age=900, ___utmvaykuNyVY=nWJx01KvGT; path=/; Max-Age=900, ___utmvbykuNyVY=JZyXEtOwalQ: PtR; path=/; Max-Age=900', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block', 'Cache-Control': 'private', 'Content-Type': 'text/html; charset=utf-8', 'Keep-Alive': 'timeout=5, max=10', 'Connection': 'Keep-Alive', 'X-Iinfo': '8-3925806-3925807 NNNN CT(73 151 0) RT(1555658593583 5) q(0 0 3 0) r(6 6) U5', 'X-CDN': 'Incapsula', 'Content-Encoding': 'gzip', 'Transfer-Encoding': 'chunked'}
Следующая команда использует редактор ed
, чтобы найти каждую строку, начинающуюся с символа табуляции, удалить этот символ и объединить строку с предыдущей строкой. Когда все строки будут обработаны, модифицированный буфер выводится на стандартный вывод.
printf '%s\n' $'g/^\t/ s///\\' '-,.j' ,p Q | ed -s file
Другой подход заключается в замене символа табуляции на какой-то однозначный символ, который не присутствует в данных, например, @
, а затем использовании YAML-парсера для удаления любого появления этого символа, когда он возникает после пробела (новая строка будет преобразована парсером в пробел, который также должен быть удален).
Используя Mike Farah’s yq
:
tr '\t' @ <file | yq 'map_values(sub(" @", ""))'
Используя Andrey Kislyuk’s yq
:
tr '\t' @ <file | yq -y 'map_values(gsub(" @"; ""))'
Ответ или решение
Использование sed
для удаления символа новой строки, не предшествующего фигурной скобке, — это задача, которая может помочь в обработке текстовых файлов, особенно в сценариях с длинными строками JSON или кодом, где строки разделены неуместно. Для достижения этой цели мы можем использовать потоковый редактор sed
с некоторыми расширенными командами для проверки условия перед заменой строки.
Подробное руководство по решению задачи
Шаги на пути к решению
-
Понимание задачи: Мы хотим удалить символ новой строки (
\n
), если предыдущий символ в строке не является закрывающей фигурной скобкой}
. Это необходимо для того, чтобы строки, которые резко обрываются, были объединены, если они не заканчиваются}
. -
Начальная попытка с
sed
:
Используем базовую командуsed
для чтения входных данных и условной манипуляции строками:sed -e :a -e '/}$/!N; s/\n//; ta' input.txt
Здесь используется метка
:a
, после которой следует цикл. Команда/}$/!N
добавляет следующую строку в буфер, если текущая строка не заканчивается на}
. Затем командаs/\n//
удаляет символ новой строки, соединяя строки. -
Удаление ведущих пробелов или табуляции:
В ситуациях, когда после соединения строк остаются ведущие пробелы или табуляции, используем:sed -e :a -e '/}$/!N; s/\n[[:blank:]]*//; ta' input.txt
Регулярное выражение
\n[[:blank:]]*
удаляет новую строку вместе с любыми последующими пробелами или символами табуляции. -
Проверка результата:
Проверьте корректность результата, чтобы все строки были правильно объединены, избегая разрывов там, где их быть не должно. -
Дополнительные замечания:
sed
полезен для обработки текстов, но может быть ограничен при работе с очень большими файлами или специфическими сценариями, где возникает необходимость в контекстном анализе.- Если данные имеют сложную структуру, возможно использование более мощных инструментов, таких как
awk
или скрипты на Python.
SEO-оптимизация и профессиональные аспекты
Включение таких ключевых слов, как "удаление новой строки в sed", "объединение строк в текстовом файле", "обработка текстовых файлов", помогает направить контент к целевой аудитории — системным администраторам и DevOps инженерам. При этом важно, чтобы описание было четким, точным и содержательным, избегая простых шаблонов и обеспечивая оригинальность подачи.
Этот подход позволяет управлять содержимым текстовых файлов более эффективно, обеспечивая чистоту и связность данных. Использование sed
в этой задаче демонстрирует его мощь и гибкость, делая его важным инструментом в арсенале ИТ-специалиста.