Назад | Перейти на главную страницу

sed / awk - найти совпадение по одной строке и изменить другую строку в той же строке

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

Мне нужно выполнить некоторые текстовые операции над файлами конфигурации json и yml, которые содержат определения некоторых каналов - структура каждой строки одинакова, кроме переменных.

Больше всего мне помогло бы выяснить, как лучше всего

1) используйте файл с определенным номером в каждой строке, чтобы указать строку в большом файле конфигурации 2) после этого возьмите эту строку и а) удалите ее из оригинала (что я знаю :) б) возьмите эту строку, найдите другую строку в это изменение - всегда одно и то же изменение, например, foo -> bar. и измените его в исходном файле - сохраните положение строки с изменением.

Моя проблема - часть 2b ... не уверен в этом, также я слышал, что у sed были проблемы с yml или json, до сих пор я использовал vim для изменения строк и т. Д., Но теперь это более конкретное - найдите строку, затем измените конкретную строку.

Если вы можете дать мне нет советов или что я могу прочитать / посмотреть, чтобы правильно понять инструменты, которые мне нужны, чтобы я мог понять это самостоятельно, буду благодарен

- {channel_id: 483, stream_profile_code: profile1, source_id: igst0-iva, source_domain: }
- {channel_id: 483, stream_profile_code: profile2, source_id: igst0-iva, source_domain: }
- {channel_id: 483, stream_profile_code: profile3, source_id: igst0-iva, source_domain: }
- {channel_id: 483, stream_profile_code: profile4, source_id: igst0-iva, source_domain: }
- {channel_id: 483, stream_profile_code: profile5, source_id: igst0-iva, source_domain: }
- {channel_id: 499, stream_profile_code: profile1, source_id: igst0-iva, source_domain: }
- {channel_id: 499, stream_profile_code: profile2, source_id: igst0-iva, source_domain: }
- {channel_id: 499, stream_profile_code: profile3, source_id: igst0-iva, source_domain: }
- {channel_id: 499, stream_profile_code: profile4, source_id: igst0-iva, source_domain: }
- {channel_id: 499, stream_profile_code: profile5, source_id: igst0-iva, source_domain: }
- {channel_id: 501, stream_profile_code: profile1, source_id: igst0-iva, source_domain: }
- {channel_id: 501, stream_profile_code: profile2, source_id: igst0-iva, source_domain: }
- {channel_id: 501, stream_profile_code: profile3, source_id: igst0-iva, source_domain: }
- {channel_id: 501, stream_profile_code: profile4, source_id: igst0-iva, source_domain: }
- {channel_id: 501, stream_profile_code: profile5, source_id: igst0-iva, source_domain: }

Здесь мне нужно найти только каждую строку, содержащую channel_id 499, и изменить igst0-iva на igst1-ven. Список идентификаторов каналов, которые мне нужно найти, находится во внешнем файле, который я уже подготовил. Это небольшой пример, его около 30 идентификаторов мне нужно изменить с 200.

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

#!/bin/sh

channel_id="499"
old_source_id="igst0-iva"
new_source_id="igst1-ven"

if [ $# -ne 2 ]; then
    echo "usage: ${0} INPUT-FILE OUTPUT-FILE"
    exit 1
fi

if [ ! -f ${1} ]; then
    echo "file ${1} does't exist"
    exit 1
fi

sed -E "s/(.*channel_id: ${channel_id}.*source_id: )(${old_source_id})(.*)/\1${new_source_id}\3/g;" ${1} > ${2}

exit $?

Ответ на мой вопрос в итоге конечно уже был здесь

исходный пост

sed -i '/STRING—TO-FIND-LINE/s/REPLACETHIS/FORTHIS/' myFile

с небольшим обновлением

while read id-FIND-LINE; do sed -i "/$id-FIND-LINE/s/REPLACETHIS/WITHTHIS/"  myFile; done < fileWithIDs