1

在我的包文件中,我有多个包。如果里面有字符串,我可以检查文件,如果是,我想获取文件的版本。

Package: depictiontest
Version: 1.0
Filename: ./debs/com.icr8zy.depictiontest.deb
Size: 810
Description: Do not install. Testing Depiction.
Name: Depiction Test

所以上面是一个包的许多类似外观信息的一部分。每次我检测到包是否存在时,我都想获取版本。有什么可能的方法吗?

顺便说一句,这是我用来检查文件是否存在的。

if grep -q "$filename" /location/Packages; then
#file exists
#get file version <-- stuck here
else
#file does not exists
fi

编辑:对不起,但也许我在解释自己时不清楚,我已经有了包的名称,并且只想提取该包的版本。我不需要循环来获取所有名称和版本。希望这可以清除它... :)

4

5 回答 5

2

首先如何提取文件名?为什么不解析整个文件,然后过滤掉不存在的文件名。

awk '/^Package:/{p=$2}
    /^Version:/{v=$2}
    /^Filename:/{f=$2}
    /^$/{print p, v, f}' Packages |
while read p v f; do
    test -e "$f" || continue
    echo "$p $v"
done

这对于例如带有空格的文件名并不可靠,但是包文件无论如何都没有带有空格的文件名。(不过,您的示例文件名是非标准的;让我们假设它并不比这更糟。)

您要确保 Packages 末尾有一个空行,或者强制使用{ sed '$/^$/d' Packages; echo; } | awk ...

编辑:这假设一个格式相当好的Packages文件,记录之间有一个空行。如果一条记录缺少这些字段之一,则输出将重复上一条记录中的值 - 这很讨厌。如果有多个相邻的空行,则会输出两次相同的包。等等。如果你想要强大的解析,我会切换到 Perl 或 Python,或者使用标准的 Debian 工具(我相信一定有一个)。

于 2012-02-06T19:08:21.363 回答
1

使用 grep,您可以在关键字之前或之后选择一定数量的行。

egrep -A1 "^Package: depictiontest" /path/to/file

比赛结束后将产生 1 条额外的线。

egrep -B1 "^Filename: .*depictiontest.*" /path/to/file

将在比赛多产生 1 行。

egrep "^(Package|Version): " "^Package: depictiontest" /path/to/file

只会导致 package 和 Version 行,因此将依赖它们以正确的顺序排列,以便轻松找出哪个版本属于哪个包。

于 2012-02-07T01:05:13.517 回答
0

如果“版本:...”行总是恰好在“文件名:...”行之前的 1 行,那么您可以尝试这样的操作:

line_number=$(grep -n "$filename" /location/Packages | head -1 | cut -d: -f1)
if (( $line_number > 0 )); then
  #file exists
  version=$(head -n $(( $line_number - 1 )) /location/Packages | tail -1 | cut -d' ' -f2)
else 
  #file doesn't exist
fi
于 2012-02-06T18:57:20.177 回答
0

如果顺序相同,那么您可以解析整个文件并将值输入到数组中 -

awk -F": " '
/^Package/{p=$2;getline;v=$2;getline;f=$2;ary[p"\n"v"\n"f"\n"]}
END{for (x in ary) print x}' file

测试:

[jaypal:~/Temp] cat file
Package: depictiontest
Version: 1.0
Filename: ./debs/com.icr8zy.depictiontest.deb
Size: 810
Description: Do not install. Testing Depiction.
Name: Depiction2fdf Test
Package: depi444ctiontest
Version: 1.05
Filename: ./debs/coffm.icr8zy.depictiontest.deb
Size: 810
Description: Do not install. Testing Depiction.
Name: Depiction Test
Package: depic33tiontest
Version: 1.01
Filename: ./d3ebs/com.icr8zy.depictiontest.deb
Size: 810
Description: Do not install. Testing Depiction.
Name: Depiction Test

[jaypal:~/Temp] awk -F": " '/^Package/{p=$2;getline;v=$2;getline;f=$2;ary[p"\n"v"\n"f"\n"]}END{for (x in ary) print x}' file
depi444ctiontest
1.05
./debs/coffm.icr8zy.depictiontest.deb

depic33tiontest
1.01
./d3ebs/com.icr8zy.depictiontest.deb

depictiontest
1.0
./debs/com.icr8zy.depictiontest.deb
于 2012-02-06T19:32:00.690 回答
0

我能想到的最简单的awk实现:

$ awk -F':' -v package='depictiontest' '
$1 == "Package" {
    trimmed_package_name = gensub(/^ */, "", "", $2)
    found_package = (trimmed_package_name == package)
}

found_package && $1 == "Version" {
    trimmed_version_number = gensub(/^ */, "", "", $2)
    print trimmed_version_number
}
' Packages
1.0

Packages这将逐行处理文件 ( ) 并设置found_package标志,如果该行以 'Package' 开头并且字段分隔符 ( -F)之后的值:(以及任何空格)是传递给package变量 ( -v) 的值。然后,如果设置了标志,我们发现一行以“版本”字段开头,我们在字段分隔符之后打印值(修剪前导空白)。如果找到另一个 'Package' 字段并且名称不是我们要查找的名称,则重置标志并且不会打印后续版本号。

于 2012-02-06T22:27:24.130 回答