4

我必须创建一个 bash 脚本,从不同的文件中 greps 多个匹配项。这些文件都包含在一个目录中,具有相同的扩展名 (.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、$URL 等),根据这个 sintax,这些变量将被打印到一个 xml 文件中:

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

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

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

4

4 回答 4

2

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

解析.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 文件的最后一行...

于 2013-06-25T13:46:47.060 回答
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 行”,所以它不应该知道区别(你的 shell 将自动调用 Python)。

于 2013-06-25T13:37:59.480 回答
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;
于 2013-06-25T13:40:51.000 回答
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
于 2013-06-25T13:36:42.180 回答