Команды AWK / Sed находят и заменяют шаблон

У меня есть файл с данными, подобными приведенным ниже. xyz может быть любым, поэтому я хочу его заменить.

variable "azure_spoke_gateways" {
  default = {
    spoke1 = {
      name         = "xyz"
      size         = "max"
      vpc          = "azure_spoke1_vnet"
    },
  }
}

variable "google_spoke_gateways" {
  default = {
    spoke1 = {
      name         = "xyz"
      size         = "max"
      vpc          = "azure_spoke1_vnet"
    },
  }
}

Я просто хочу заменить значение переменной azure_spoke_gateways имя . Желаемый результат:

  variable "azure_spoke_gateways" {
      default = {
        spoke1 = {
          name         = "MYSTRING"
          size         = "max"
          vpc          = "azure_spoke1_vnet"
        },
      }
    }
0
задан 11 December 2020 в 18:17

4 ответа

Вы можете использовать эту команду Perl:

perl -0777 -pe 's/(variable "azure_spoke_gateways".*?name *= *)".*?"/\1"MYSTRING"/gs' input_file

Она заменит все, что находится внутри "" (не только xyz ) для имени на MYSTRING .

Если вы хотите заменить только xyz , используйте:

perl -0777 -pe 's/(variable "azure_spoke_gateways".*?name *= *)"xyz"/\1"MYSTRING"/gs' input_file

Чтобы изменить input_file на месте, добавьте -i флаг прямо перед input_file .

0
ответ дан 3 January 2021 в 22:46

С sed :

sed '/^variable "azure_spoke_gateways"\s*{$/ , /^\s*name[^=]*=\s*"[^"]*"$/{
    s/\(name[^=]*=\).*/\1 "MYSTRING"/; }' infile
0
ответ дан 3 January 2021 в 22:46

Обычно вы можете анализировать построчно в более простых форматах, пока вы отслеживаете подраздел.

awk '  
  match($0,/variable "([^"]+)" {/,m) {  
    v = m[1]  
  }  
  $1 ~ /name/{  
    if(v == "azure_spoke_gateways") {  
      gsub(/"[^"]+"$/, "\"MYSTRING\"", $0)  
    }  
  } 1' data

Вы также можете сделать его как файл сценария.

#!/usr/bin/awk -f

match($0,/variable "([^"]+)" {/,m) {
    v = m[1]
}
v == "google_spoke_gateways" {
    if($1 == "name"){
        gsub(/"[^"]+"$/, "\"MYSTRING\"", $0)
    }
    if($1 == "size") {
        gsub(/"[^"]+"$/, "\"min\"", $0)
    }
    if($1 == "vpc") {
        gsub(/"[^"]+"$/, "\"google_spoke1_vnet\"", $0)
    }
} 1

И вы запускаете сценарий следующим образом.

awk -f script.awk < data
0
ответ дан 3 January 2021 в 22:46

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

 gawk -vRS= -vmystring='"MYSTRING"' '
   BEGIN {OFS=FS="\n"} 
   $1 ~ /"azure_spoke_gateways"/ {
     for(i=1;i<=NF;i++) {
       if($i ~ /^[[:blank:]]*name[[:blank:]]*=/) sub(/"xyz"/,mystring,$i)
     }
   } {printf $0 RT}
 ' file

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

Если у вас нет GNU awk (gawk), вы можете использовать обычный awk, но не сможете использовать RT , чтобы заменить фактические разделители записей - вам нужно установить ORS на что-то фиксированное, например \ n \ n .

0
ответ дан 3 January 2021 в 22:46

Другие вопросы по тегам:

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