Grep multiple lines from different files and print them in xml

I need to create a bash script that combines multiple matches from different files. All files are included in the directory with the same extension (.desktop). Here is an example:

[Desktop Entry] Icon=text-x-c++src Name=button.cpp Type=Link URL[$e]=file://$HOME/Configs/button.cpp X-KDE-LastOpenedWith=kate 

Matches are URL, LastOpenedWith, Name and Icon. Each of them should be stored in another variable (for example, $ Name, $ URL, etc.), Which will be printed in an XML file, according to this sintax:

 <action label="$Name" icon="$Icon" exec="$LastOpenedWith $URL"/> 

Create separate entries for all .desktop files.

I do not know how to do this, since I start with bash scripts, any feedback would be welcome :)

+4
source share
4 answers

Something like this might work:

 echo -e "<menu>\n<submenu>" > output.xml for f in *.desktop; do Icon=$(awk -F= '/Icon/{print $2}' "$f") Name=$(awk -F= '/Name/{print $2}' "$f") URL=$(awk -F= '/URL/{print $2}' "$f") LastOpenedWith=$(awk -F= '/X-KDE-LastOpenedWith/{print $2}' "$f") echo "<action label=\"$Name\" icon=\"$Icon\" exec=\"$LastOpenedWith $URL\"/>" done >> output.xml echo -e "</submenu>\n</menu>" >> output.xml 

A Perl solution using Config :: IniFiles might look like this:

 #!/usr/bin/env perl use strict; use warnings; use Config::IniFiles; open XML, ">/path/to/output.xml" or die $!; print XML "<menu>\n<submenu>\n"; foreach my $file (</path/to/*.desktop>) { my $ini = Config::IniFiles->new( -file => "$file" ); printf XML "<action label='%s' icon='%s' exec='%s %s'/>\n", $ini->val('Desktop Entry', 'Name'), $ini->val('Desktop Entry', 'Icon'), $ini->val('Desktop Entry', 'X-KDE-LastOpenedWith'), $ini->val('Desktop Entry', 'URL[$e]') } print XML "</submenu>\n</menu>\n"; close XML; 
+1
source

you can do it in one awk script:

parse.awk:

 #!/usr/bin/awk -f BEGIN { FS="=" } /^Name/ { name=$2 } /^Icon/ { icon=$2 } /^URL/ { url=$2 } /LastOpenedWith/ { lastopenedwith=$2 printf("<action label=\"%s\" icon=\"%s\" exec=\"%s %s\"/>\n", name, icon, lastopenedwith, url) } 

causing

 ./parse.awk *.desktop 

this script work assuming X-KDE-LastOpenedWith is found on the last line of each * .desktop ...

+2
source

Since you are saying that you are new to Bash, here is the solution: use Python. This is a much better programming language, and it has a library for parsing configuration files, like the ones you deal with: http://docs.python.org/library/configparser.html , It can also write easily XML, and unlike Bash, you will not need to learn a second language, such as sed , to complete the task - you can do everything with Python.

Edit: here you go, Python program:

 #!/usr/bin/env python import ConfigParser import sys for filename in sys.argv[1:]: # each argument except the program name itself parser = ConfigParser.RawConfigParser() parser.read(filename) name = parser.get('Desktop Entry', 'Name') icon = parser.get('Desktop Entry', 'Icon') app = parser.get('Desktop Entry', 'X-KDE-LastOpenedWith') url = parser.get('Desktop Entry', 'URL[$e]') print '<action label="{}" icon="{}" exec="{} {}"/>'.format(name, icon, app, url) 

And since you said that the calling program is expecting a shell script, I included the line β€œshebang” at the top so that it does not know the difference (your shell will automatically call Python).

+1
source
 #This functions gets a field from a ".desktop" file get_variable() { FILE=$1 FIELD=$2 #grep the lines that starts with the fields and cuts them after '=' char grep -m 1 -e "^$FIELD" "$FILE" | cut -f 2 -d"=" } #gets all the .desktop files in the current folder #gets the specified fields from them for file in *.desktop; do name=get_variable "$file" "Name" type=get_variable "$file" "Type" icon=get_variable "$file" "Icon" url=get_variable "$file" "URL" last=get_variable "$file" "X-KDE-LastOpenedWith" #echo the XML file echo "<action label=\"$name\" icon=\"$icon\" exec=\"$last $url\"/> " done 
0
source

Source: https://habr.com/ru/post/1488089/


All Articles