从文件中获取字符串

时间:2012-02-06 17:50:37

标签: linux bash grep packages deb

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

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

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

5 个答案:

答案 0 :(得分: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

这对于例如带有空格的文件名,但包文件没有带空格的文件名。 (你的示例文件名是非标准的,但我们假设它并不比这更差。)

您希望确保在包的末尾有一个空行,或者强制它{ sed '$/^$/d' Packages; echo; } | awk ...

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

答案 1 :(得分:1)

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

egrep -A1 "^Package: depictiontest" /path/to/file
在匹配后,

会产生1个额外的行。

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

匹配之前会产生额外的一行

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

只会导致包和版本行,所以依赖于它们的顺序正确,找出哪个版本属于哪个包。

答案 2 :(得分:0)

如果“Version:...”行在“Filename:...”行之前总是正好一行,那么您可以尝试这样的事情:

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

答案 3 :(得分: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

答案 4 :(得分: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),如果行以'Package'开头,则设置found_package标志,并在字段分隔符后面设置值-F) ,:(和任何空格)是传递给package变量(-v)的值。然后,如果设置了标志,我们找到以“Version”字段开头的行,我们在字段分隔符之后打印该值(修剪前导空格)。如果找到另一个“包”字段且名称不是我们要查找的字段,则重置该标志并且不会打印后续版本号。