从不同文件中刷出多行,并将它们打印到xml

时间:2013-06-25 13:10:31

标签: bash

我必须创建一个bash脚本,用于处理来自不同文件的多个匹配项。这些文件都包含在目录中,具有相同的扩展名(.desktop)。这是一个例子:

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

匹配是URL,LastOpenedWith,Name和Icon。它们中的每一个都必须存储到一个不同的变量(例如$ Name,$ URL等)中,这些变量将被打印到xml文件中,相应于这个sintax:

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

为所有.desktop文件创建单个条目。

我真的不知道怎么做,因为我是bash脚本的初学者,欢迎任何提示:)

4 个答案:

答案 0 :(得分:2)

您可以在一个awk脚本中执行此操作:

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)
}

致电

./parse.awk *.desktop

这个脚本的工作假设X-KDE-LastOpenedWith出现在每个* .desktop文件的最后一行......

答案 1 :(得分:1)

既然你说你是Bash的新手,那么这是一个解决方案:使用Python。它是一种更好的编程语言,它附带了一个用于解析配置文件的库,就像你正在处理的那样:http://docs.python.org/library/configparser.html。它也可以轻松编写XML,与Bash不同,您不必学习第二语言sed来完成工作 - 您可以使用Python完成所有工作。

编辑:这是一个Python程序:

#!/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)

既然你说调用程序需要一个shell脚本,我在顶部包含了“shebang line”,所以它不应该知道它们的区别(你的shell会自动调用Python)。

答案 2 :(得分:1)

这样的事可能有用:

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

使用Config::IniFiles的Perl解决方案可能如下所示:

#!/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;

答案 3 :(得分:0)

#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