I need to parse multiple files from asterisk to get informations that refer to same objects but are stored in different positions (ideally I would like to get the sectionname reference).
Now I look for a specific string with:
grep -OPTIONS /DIRECTORY -e SEARCHSTRING
OPTIONS
-r, --recursive
Read all files under each directory, recursively, following symbolic links only if they are on the command line. This is equivalent to the -d recurse option.
-n, --line-number
Prefix each line of output with the 1-based line number within its input file. (-n is specified by POSIX.)
i.e. seach string "outrt-5" in folder /etc/asterisk:
# grep -rn /etc/asterisk/ -e outrt-5
/etc/asterisk/extensions_additional.conf:4462:include => outrt-5 ; test
/etc/asterisk/extensions_additional.conf:4662:[outrt-5] ; test
/etc/asterisk/extensions_additional.conf:4663:include => outrt-5-custom
/etc/asterisk/extensions_additional.conf:4677:;--== end of [outrt-5] ==--;
Now I've retrieved the single line number reference and filenames.
How can I retrieve all the rows in the section or at least the nameofsection (a section is delimited by [nameofsection] )?
Is sed - stream editor for filtering and transforming text the best option?
# STARTROW=4460
# NEXTROW=4462
# ENDROW=4462
sed -n "${STARTROW}, ${NEXTROW} p; ${ENDROW} q" /etc/asterisk/extensions_additional.conf
i.e. /etc/asterisk/extensions_additional.conf section near line:4462:
[outbound-allroutes]
include => outbound-allroutes-custom
include => outrt-5 ; test
So now you can see that outrt-5 is inside outbound-allroutes
Is there a way to get as search result:
> /etc/asterisk/extensions_additional.conf:4462:include => outrt-5 ;[outbound-allroutes]
?
I generally use sed
for simple block selection scripts. For example -
$: cat file # note that there is NO blank line at the end
[outbound-allroutes]
include => outbound-allroutes-custom
include => outrt-1 ; test first block
[outbound-allroutes]
include => outbound-allroutes-custom
include => nope-5 ; test
[outbound-allroutes]
include => outbound-allroutes-custom
include => outrt-2 ; test embedded block
[outbound-allroutes]
include => outbound-allroutes-custom
include => nope-5 ; test
[outbound-allroutes]
include => outbound-allroutes-custom
include => nope-5 ; test
[outbound-allroutes]
include => outbound-allroutes-custom
include => outrt-3 ; test last/END block
I'm going to grab every block that has outrt
. You can modify the logic a bit to fit your exact needs.
$: cat tst
sed -n '
/\[.*\]/,/^[[:space:]]*$/{
/\[.*\]/{h; n;}
/^[[:space:]]*$/{ H; x; /outrt/{p; n;} }
H;
}
${ x; /outrt/p }
' file
$: ./tst
[outbound-allroutes]
include => outbound-allroutes-custom
include => outrt-1 ; test first block
[outbound-allroutes]
include => outbound-allroutes-custom
include => outrt-2 ; test embedded block
[outbound-allroutes]
include => outbound-allroutes-custom
include => outrt-3 ; test last/END block
This is GNU sed
. If you don't have that we'll need to make some modifications.
grep
is good, but it doesn't really allow complex logic that defines arbitrary length multiline data.
All that being said, as William Pursell pointed out, awk
can make this sort of thing trivial if you know how. Using the same input file -
$: awk -v RS= '/outrt/{print $0 "\n"}' file
[outbound-allroutes]
include => outbound-allroutes-custom
include => outrt-1 ; test first block
[outbound-allroutes]
include => outbound-allroutes-custom
include => outrt-2 ; test embedded block
[outbound-allroutes]
include => outbound-allroutes-custom
include => outrt-3 ; test last/END block