![在具有多个部分的文件的一个部分中查找字符串](https://linux22.com/image/56358/%E5%9C%A8%E5%85%B7%E6%9C%89%E5%A4%9A%E4%B8%AA%E9%83%A8%E5%88%86%E7%9A%84%E6%96%87%E4%BB%B6%E7%9A%84%E4%B8%80%E4%B8%AA%E9%83%A8%E5%88%86%E4%B8%AD%E6%9F%A5%E6%89%BE%E5%AD%97%E7%AC%A6%E4%B8%B2.png)
如何使用 sed/awk 获取另一个字符串中包含的字符串。
TESTVAR='
{
icon : "icons/773_l.png",
id : 80,
initialState : true,
isPng : false,
label : "Imagery",
opacity : 1,
requestType : "UUID",
version : 79
}
,
{
icon : "thisicon",
id : 8080,
initialState : false,
isPng : true,
label : "Boundaries",
opacity : 1,
requestType : "NothingSpecial",
version : 8
}
version : 79
我需要为包含 的对象选择requestType : "UUID"
。我如何选择第一个块内的所有内容,然后选择版本,然后只使用命令 return 79
。我已经尝试了一段时间,但不知道如何只选择第一个之间的所有内容{}
。一旦我有了这个,我就只需要得到之后的号码version :
。
我以为这会起作用,但事实并非如此awk '/\{/{f=1;next}/\}/{f=0}f' test.txt
此外,订单无法保证。所以我真的需要选择里面包含“UUID”的所有{
内容}
。然后选择version : \([0-9]+\)
这很接近但太贪心了:sed -e 's/{\(.*UUID.*\)}/\1/' test.txt
答案1
首先我想到的既不是 sed 也不是 awk:
$ tr -d '\n' < file | grep -Po 'requestType : "UUID"\K.*? version : \K[0-9]*'
79
可能可以更容易地完成,特别是如果您可以保证“version”紧随“requestType”之后。
如果version
不需要让requested Type
事情变得更复杂一点:
$ tr -d '\n' < file | grep -Po '{.[^}]*?requestType : "UUID".*?}' | grep -Po 'version : \K[0-9]*'
79
如果有更多可以匹配所有部分的部分将被打印:
$ cat file
TESTVAR='
{
icon : "icons/773_l.png",
id : 80,
initialState : true,
isPng : false,
label : "Imagery",
opacity : 1,
version : 79,
requestType : "UUID"
}
,
{
icon : "thisicon",
id : 8080,
initialState : false,
isPng : true,
label : "Boundaries",
opacity : 1,
requestType : "NothingSpecial",
version : 8
}
,
{
icon : "icons/773_l.png",
id : 80,
initialState : true,
isPng : false,
label : "Imagery",
opacity : 1,
requestType : "UUID",
version : 87
}
,
{
icon : "icons/773_l.png",
id : 80,
version : 17,
initialState : true,
isPng : false,
label : "Imagery",
opacity : 1,
requestType : "UUID"
}
,
{
icon : "thisicon",
id : 8080,
requestType : "NothingSpecial",
initialState : false,
label : "Boundaries",
opacity : 1,
version : 18,
isPng : true
}
$ tr -d '\n' < file | grep -Po '{.[^}]*?requestType : "UUID".*?}' | grep -Po 'version : \K[0-9]*'
79
87
17
答案2
awk 允许您定义记录分隔符,因此不要使用换行符(每行都是一条记录),而是使用“}\n”作为记录的结尾:
echo "$TESTVAR" |
gawk -v RS="}\n" '
/requestType : "UUID"/ && match($0, /version : ([0-9]+)/, m) {print m[1]}
'
79
这是 GNU awk 特有的,用于 match() 函数。
可惜这不是有效的 JSON。然后你可以使用 JSON 解析器:
jq '(.[] | select(.requestType == "UUID")).version' <<JSON
[
{
"icon" : "icons/773_l.png",
"id" : 80,
"initialState" : true,
"isPng" : false,
"label" : "Imagery",
"opacity" : 1,
"requestType" : "UUID",
"version" : 79
}
,
{
"icon" : "thisicon",
"id" : 8080,
"initialState" : false,
"isPng" : true,
"label" : "Boundaries",
"opacity" : 1,
"requestType" : "NothingSpecial",
"version" : 8
}
]
JSON
答案3
这是纯粹使用以下方法来做到这一点的一种方法sed
:
$ sed -rn '/\{/{:a;N;/\}/{/requestType : "UUID"/s/.*version : ([0-9]+).*/\1/p;d};ba}' <<< "$TESTVAR"
79
$
这是改编自https://stackoverflow.com/a/18046021/2113226为了您的数据。
你提到这是一个javascript数据结构,所以我认为解析它的最可靠的方法是使用javascript。我安装了 Node.js 来执行此操作,但我认为任何命令行 javascript 解释器都应该能够执行如下操作:
$ echo "arr=[$TESTVAR]; console.log(arr.filter(function(elem) { return elem.requestType === \"UUID\"; })[0].version)" | node
79
$
免责声明
您必须确保这里的数据安全。我不太了解 javascript,但我认为如果输入数据字符串制作得当,代码注入是完全有可能的。