Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 从文件中获取字符串_Linux_Bash_Grep_Packages_Deb - Fatal编程技术网

Linux 从文件中获取字符串

Linux 从文件中获取字符串,linux,bash,grep,packages,deb,Linux,Bash,Grep,Packages,Deb,在我的包文件中,我有多个包。我可以检查文件中是否有字符串,如果有,我想获取文件的版本 Package: depictiontest Version: 1.0 Filename: ./debs/com.icr8zy.depictiontest.deb Size: 810 Description: Do not install. Testing Depiction. Name: Depiction Test 因此,上面的内容是一个包中许多相似信息的一部分。每次我检测到包是否存在时,我都希望获得版本

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

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
if grep-q“$filename”/location/Packages;然后
#文件存在
#获取文件版本如果“版本:…”行始终正好位于“文件名:…”行之前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

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

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…


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

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

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
测试:
我能想到的最简单的
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”开头,并且字段分隔符(
-F
)后面的值是传递到
package
变量(
-v
)中的值,则设置
found\u package
标志。然后,如果将该标志设置为“我们找到一行以“Version”字段开头,我们将在字段分隔符后打印该值(修剪前导空格)。如果找到另一个“Package”字段,并且名称不是我们要查找的名称,则会重置标志,并且不会打印后续版本号。

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

egrep -A1 "^Package: depictiontest" /path/to/file
将在比赛后产生1条额外的线

egrep -B1 "^Filename: .*depictiontest.*" /path/to/file
egrep "^(Package|Version): " "^Package: depictiontest" /path/to/file
将在比赛前产生1条额外的线

egrep -B1 "^Filename: .*depictiontest.*" /path/to/file
egrep "^(Package|Version): " "^Package: depictiontest" /path/to/file

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

这假定标头具有固定的顺序。不是很健壮。是的,我提到我的解决方案取决于顺序,不是吗?)从你的评论中看,它不明显需要立即进行。啊,看到你的工作解决方案被否决在零票以下总是令人高兴的-谢谢你,未知的陌生人!:)明白了-有一个输入错误,所以,从技术上讲,我的解决方案不起作用。否决权很酷!:)