регулярное выражение в sed для замены определенной строки

#regex #sed

Вопрос:

У меня есть досье config.txt которые состоят из строк, как показано ниже

 $ cat config.txt | head -n 3
f03889d9abcb6a16155411bb8e0a34dddb5c8e4c@192.168.3.4:26601
be9d757acee1f5b573ec18d1e056542bc282be23@169.172.56.77:26604
d40ec20a080468fcd5965493d904e4d536cf5767@10.129.101.3:26607

$ cat ip.txt | head -n 3
10.0.4.5
10.3.5.6
10.3.5.8
 

Я хотел бы заменить IP-адрес на config.txt с включенным ip ip.txt файл соответственно

ожидаемый результат составляет

 f03889d9abcb6a16155411bb8e0a34dddb5c8e4c@10.0.4.5:26601
be9d757acee1f5b573ec18d1e056542bc282be23@10.3.5.6:26604
d40ec20a080468fcd5965493d904e4d536cf5767@10.3.5.8:26607
 

Поскольку IP-адреса в файле конфигурации являются динамическими, мне нужно использовать регулярное выражение в sed для замены IP-адреса.
для примера:

 $ echo "f03889d9abcb6a16155411bb8e0a34dddb5c8e4c@192.168.3.4:26601" | sed "s/*@ :*/*@10.0.4.5:*/g"
 

но это не обновление ip-адресов. Я очень новичок в регулярном выражении в написании сценариев. Пожалуйста, помогите!

Комментарии:

1. Избегайте Бесполезного Использования Cat ™ с head -n3 config.txt , кстати.

Ответ №1:

Ну, в этом случае можно использовать sed и регулярное выражение. Вы можете сначала объединить файлы, а затем использовать регулярное выражение для перетасовки строк:

 paste config.txt ip.txt | sed 's/@[^:]*(.*)t(.*)/@21/'
 

Обратите внимание, что это sed работает только в контексте одной строки. Но регулярное выражение не является «динамическим», если the ip's in config file are dynamic тогда вам следует использовать что-то «большее», чем регулярное выражение, лучше полный язык программирования с поддержкой карт и внутреннего состояния, например awk , но также perl или python .

Ответ №2:

Способ использования awk вместо этого. Сначала он считывает ip.txt и сохраняет свое содержимое в массиве, индексируемом по номеру строки , а затем для каждой строки config.txt заменяет IP-адрес в нем на адрес из соответствующей строки ip.txt :

 $ awk 'FNR==NR { ips[FNR] = $0; next }
       { sub(/@[^:] :/, "@" ips[FNR] ":"); print }' ip.txt config.txt
f03889d9abcb6a16155411bb8e0a34dddb5c8e4c@10.0.4.5:26601
be9d757acee1f5b573ec18d1e056542bc282be23@10.3.5.6:26604
d40ec20a080468fcd5965493d904e4d536cf5767@10.3.5.8:26607
 

Ответ №3:

Другой способ:

 paste -d~ config.txt ip.txt | while IFS="~" read config ip; 
do
echo $config | sed -r "s/([a-z0-9] )@(([0-9]{1,3}.?){4})(:[0-9] )/1@$ip4/g";
done;
 

Ответ №4:

Вот чистый ответ sed. Я прокомментировал это. Выложи содержимое на мой.сед и зови сед -н -ф мой.сед config.txt ip.txt

 # We concat config.txt and ip.txt to a single line like
# f...c@192.168.3.4:26601|b...3@169.172.56.77:26604|d...7@10.129.101.3:26607|;10.0.4.5;10.3.5.6;10.3.5.8
# the characters "|" and ";" are used as separators
# the records of config.txt are identified by @,
# those of ip.txt the pattern ^[0-9](.[0-9]){3}

# if it's a config.txt line append "|" and append it to the hold space
/@/ {
    s/$/|/
    H
}
# if it's a ip.txt line put a ";" before it and append it to the hold space
/^[0-9] (.[0-9] ){3}/ {
    s/^/;/
    H
}
# Now the two files are read. We do the replacements at the end of input
$ { 
    x
    # after having deleted all newlines the pattern spaces consists
    # of one line as mentioned above
    s/n//g
    :b
    # now we replace recursively the ip adress in the first "|"
    # limited column by the ip adress in
    # the first ";" limited column. (:b ist the beginning of the loop) 
    # 1. group: sequence of not | characters ended by @<ip-adress>:<not | characters>
    # 2. group: the characters including the "@"
    # 3. group: part of the ip adress pattern
    # 4. group: the characters from : to "|" (excluded)
    # 5. group: the sequence of not ";" characters followed by ";"
    # 6. group: the replacement ip adress
    # 7. group: part of the replacement ip adress pattern
    # The "," in the replacement replaces the first "|" in order
    # to enable recursion (see 1. group above)

    s/(([^|]*@)[0-9] (.[0-9] ){3}(:[^|]*))|([^;]*);([0-9] (.[0-9] ){3})/264,5/
    tb
    # replace all , except the last one with newlines
    s/,(.)/n1/g
    # replace the last ","
    s/,//
    p
}
 

Ответ №5:

Это может сработать для вас (GNU sed amp; cat):

 cat -n ipFile | sed -E 's/t(.*)/s#@.*:#@1:#/' | sed -f - configFile
 

Добавьте номера строк в IP-файл.

Замените каждую строку в IP-файле командой подстановки sed для ip-адреса.

Вызовите второе приложение sed, используя файл конфигурации в качестве источника, и примените команду подстановки из файла IP к каждой строке в файле.

N. B. -f Опция принимает команду sed из файла, в этом случае файл - передается по конвейеру из предыдущего приложения sed.


Другое решение:

 paste configFile ipFile | sed -E 's/@.*:(S*)t(S )/@2:1/;/@/!d'
 

Это заменит добавленный ip-адрес в файле конфигурации.

N. B. Если в IP-файле больше строк, чем /@/!d в файле конфигурации, убедитесь, что дополнительные строки не включены.