Reputation: 152
My tf variables file has 200+ variables. Here are some conflicting variables when I try awk:
variable "vm_ami" {
type = string
description = "ami image id used for setting up the vm"
default = "ami-5157cd3f"
}
variable "vm_mount_name" {
type = string
description = "mount point for new device"
default = "xvdb"
#default = "xvdb"
}
variable "vm_device_name" {
type = string
description = "device name for new drive"
default = "xvdb"
#default = "nvme1n1"
}
variable "elb_account_id" {
type = string
description = "account id for elb"
default = "01234567890"
}
variable "account_id" {
type = string
description = "Account number"
default = "0987654321"
}
I want to print 0987654321
(account ID). For that, I tried:
awk 'c&&!--c;/account_id/{c=3}' variables.tf
Gives:
default = "01234567890"
default = "0987654321"
.
awk 'c&&!--c;/account_id/{c=3}' variables.tf | cut -d '=' -f 2
Gives:
"01234567890"
"0987654321"
how can i print just : 0987654321
(without double quotes)
Upvotes: 0
Views: 142
Reputation: 10123
With sed
:
sed -n '
/variable "account_id"/,/^[[:blank:]]*}[[:blank:]]*$/ {
/^[[:blank:]]*default[[:blank:]]*=[[:blank:]]*"\(.*\)".*/ {
s//\1/p; q;
}
}' file
Explanation:
Assumptions: In the input, there is exactly one line matching the string variable "account_id"
, and there is exactly one line matching the string default = "..."
between the first matching line and the line consisting of }
.
The address range /variable "account_id"/,/^[[:blank:]]*}[[:blank:]]*$/
matches the lines starting from the line containing the string variable "account_id"
, and continues until the line consisting solely of a single }
, optionally with leading and/or trailing blank characters (spaces or tabs). You can simplify the second address as /^}$/
if you're sure that there will be no blanks in this line.
The regular expression [[:blank:]]*
matches zero or more consecutive blank characters. The regex ^[[:blank:]]*default[[:blank:]]*=[[:blank:]]*"\(.*\)".*
matches the entire line which has the form default="..."
, possibly with leading or intervening blank characters, and captures the string between double quotes ("\(.*\)"
).
The substitution command s//\1/p
replaces the entire line with the string captured previously (between double quotes), then prints it out. The empty regular expression //
repeats the last regular expression match.
The q
command exits the sed
without processing any more commands or input.
Upvotes: 1
Reputation: 203189
With GNU awk for FPAT to easily identify fields and then creating an array (f[]
below) to map the field names to their values, you can just reference the values you want by their names:
$ awk -v FPAT='[[:alnum:]_]+|"[^"]*"' '
{ gsub(/^"|"$/,"",$2); f[$1]=$2 }
/^}/ && (f["variable"] == "account_id") { print f["default"] }
' file
0987654321
With that approach it's trivial to test whatever you like and print whatever you like in whatever order you like, e.g.:
$ awk -v FPAT='[[:alnum:]_]+|"[^"]*"' -v OFS=',' '
{ gsub(/^"|"$/,"",$2); f[$1]=$2 }
/^}/ && ( (f["variable"] == "account_id") || (f["description"] ~ /new/) ) {
print f["description"], f["default"]
}
' file
mount point for new device,xvdb
device name for new drive,nvme1n1
Account number,0987654321
Upvotes: 1
Reputation: 52334
This is a bit heavy weight and more of a thought experiment, but that file is basically tcl syntax, which means it's easy to use tcl to create a simple DSL to parse the file and then extract the desired information.
#!/usr/bin/env tclsh
# Create a new sandboxed interpreter and create functions to store
# variables and their sub-fields in an array. Treat the sub-fields as
# commands of their own to be evaluated instead of just doing a
# straight list search for default to avoid things like
# # default = "bad" matching.
set i [interp create -safe]
interp eval $i {
proc type {_ arg} {
global vars varname
set vars($varname,type) $arg
}
proc description {_ arg} {
global vars varname
set vars($varname,description) $arg
}
proc default {_ arg} {
global vars varname
set vars($varname,default) $arg
}
proc variable {name body} {
global varname
set varname $name
eval $body
}
}
lassign $argv filename varname
# Evaluate the file
interp invokehidden $i source $filename
# And extract the default argument of the given variable
puts [interp eval $i [list set vars($varname,default)]]
Sample usage:
$ ./getvar variables.tf account_id
0987654321
Upvotes: 0
Reputation: 103744
Given:
$ cat file
variable "vm_ami" {
type = string
description = "ami image id used for setting up the vm"
default = "ami-5157cd3f"
}
variable "vm_mount_name" {
type = string
description = "mount point for new device"
default = "xvdb"
#default = "xvdb"
}
variable "vm_device_name" {
type = string
description = "device name for new drive"
default = "xvdb"
#default = "nvme1n1"
}
variable "elb_account_id" {
type = string
description = "account id for elb"
default = "01234567890"
}
variable "account_id" {
type = string
description = "Account number"
default = "0987654321"
}
You can use Perl to read the file as one string and use multi-line regex to parse the blocks:
perl -0777 -ne 'while (/^variable\h+"([^"]+)"([^}]+})/gm) {
if ($1 eq "account_id") {
$2=~m/\h+default\h+[^"]+"(\d+)/;
print $1;
}
}' file
0987654321
Or this GNU awk works as well:
gawk 'BEGIN{ RS = "\n\\s*variable\\s" ; FS="\n"}
/"account_id"/ {
for (i=1;i<=NF; i++) {
if ($i~/\sdefault\s/) {
match($i, /^[^"]*"([^"]*)/, matches)
print matches[1]
}
}
} ' file
Upvotes: 1