Reputation: 688
I have a valid YAML:
---
name: first
metadata: a
---
name: second
metadata: b
---
name: third
metadata: c
How can I split it using a one-liner AWK script in files first.yaml
, second.yaml
and third.yaml
? Solution needs to work with any name
.
Just splitting the file works but I can't figure out how to add proper file names instead of line numbers (NR
):
awk '/\-\-\-/{f=NR".yaml"}; {print >f}'
Upvotes: 7
Views: 19618
Reputation: 7297
To simplify things I'd do this in two steps. First split test.yaml
into separate files like this:
$ cat test.yaml
---
name: first
metadata: a
---
name: second
metadata: b
---
name: third
metadata: c
$ awk '
BEGIN{i=0}
/^name:/{i++}
/^---$/{next}
{print > "test"i".yaml"}
' test.yaml
$ ls
test1.yaml test2.yaml test3.yaml test.yaml
Second, rename files like this:
for yaml in test?.yaml; do
name=$(awk '/^name:/{print $2}' "$yaml")
mv "$yaml" "$name".yaml
done
$ ls
first.yaml second.yaml test.yaml third.yaml
$ cat first.yaml
name: first
metadata: a
Upvotes: 0
Reputation: 468
You can do it simply using the package yq
:
yq -s '.name' file.yml
Upvotes: 13
Reputation: 29
Here is another way:
This is to address if name: is in the middle like many kubernetes yaml files.
awk '/^..name:/{file=$2 ".yaml"} !/^-/{temp=temp $0 "\n"} /^-/{print temp>file; close(file); temp=""}' inputFile
Please note, this expects the
name: to start after two spaces.
Upvotes: -2
Reputation: 204164
awk '/^name:/{close(out); out=$2 ".yaml"} !/^-+$/{print > out}' file
Upvotes: 3
Reputation: 37424
Here's another:
$ awk -v RS="---\n" 'NR>1{f=$2 ".yaml";printf "%s",$0 > f;close(f)}' file
Results:
$ cat first.yaml
name: first
metadata: a
It worked with GNU awk, mawk and busybox awk but produced a leeding empty line on awk version 20121220.
Upvotes: 1
Reputation: 133650
EDIT: Adding 1 more solution.
awk '
/name:/{
close(file)
file=$NF".yaml"
}
file!="" && !/^--/{
print > (file)
}
' Input_file
Could you please try following.
awk '
prev!=file{
close(prev)
}
/name:/{
file=$NF".yaml"
}
file!="" && !/^--/{
print > (file)
prev=file
}
' Input_file
Sample output file will be:
cat first.yaml
name: first
metadata: a
Explanation: Adding detailed explanation for above code.
awk ' ##Starting awk program from here.
prev!=file{ ##Checking condition if prev is NOT equal to file variable then do following.
close(prev) ##Closing output file, to avoid too many files opened in back-end by mentioning close(prev) command here.
} ##Closing condition prev!=file here.
/name:/{ ##Checking condition if line has string name: in it then do following.
file=$NF".yaml" ##Creating variable named file whose value is $NF(last field of current line) .yaml
} ##Closing name: condition here.
file!="" && !/^--/{ ##Checking condition if variable file is NOT NULL AND line is NOT starting with dash then do following.
print > (file) ##Printing current line into output file whose name is there in file variable.
prev=file ##Setting prev variable whose value is variable file here.
} ##Closing BLOCK for file!="" && !/^--/ condition here.
' Input_file ##Mentioning Input_file name here.
Upvotes: 4