Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/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
Regex 如何使用bash脚本将.txt文件中的所有键值对传输到数组_Regex_Bash_Shell_Grep_Jq - Fatal编程技术网

Regex 如何使用bash脚本将.txt文件中的所有键值对传输到数组

Regex 如何使用bash脚本将.txt文件中的所有键值对传输到数组,regex,bash,shell,grep,jq,Regex,Bash,Shell,Grep,Jq,我有一个变量var,它包含如下所示的json文本 var='{ "user": "jack","password": "kilby","install":"False", "deploy":"False", "build":"123","ip":"0.0.0.0" }' 我正在把它写入一个.txt文件 touch properties.txt destdir=./properties.txt if [ -f "$destdir" ] then echo "$var" >

我有一个变量var,它包含如下所示的json文本

 var='{ "user": "jack","password": "kilby","install":"False", "deploy":"False", "build":"123","ip":"0.0.0.0" }'
我正在把它写入一个.txt文件

touch properties.txt

destdir=./properties.txt

if [ -f "$destdir" ]
then 
    echo "$var" > "$destdir"
fi
然后我必须将所有键值对存储在一个数组中,以便进一步处理,如下所示

arr=( $(grep -o \"[^\"]*. properties.txt) )
因此,双引号中的所有文本都被移动到arr

但问题是,如果键值对如下图所示,即如果值为空,则arr将\作为一个条目获取,这是不可取消的

{"k1":"","k2":"","k3":""}
在这种情况下,我需要一个空字符串作为arr的条目进入

我不太了解bash命令。所以谢谢你的帮助。 如果使用jq库可以获得结果,那么这些建议也是受欢迎的。 谢谢

考虑一下:

$ jq -c 'keys[] as $k | ($k, .[$k])' <<< "$var"
"build"
"123"
"deploy"
"False"
"install"
"False"
"ip"
"0.0.0.0"
"password"
"kilby"
"user"
"jack"
有关更多详细信息,请参阅

警告
你没有说你的最终目标是什么,但我怀疑你最好更全面地使用jq来实现它

首先,我将创建一个返回数组内容的函数

function myvar {
   cat << "END"
{ "user": "jack","password": "kilby","install":"False", "deploy":"False", "build":"123","ip":"0.0.0.0" }
END
}

现在我们有了这些,我们可以通过采购来评估结果。在寻找数据源之前,我们将使用一个勾号将其作为一个文件:不想判断您选择的解析此类数据的方法是否正确,我将尝试回答您的问题,即使我不同意您选择的解析json数据的方法

在代码的这一点上,您创建了一个名为arr的数组:

arr=( $(grep -o \"[^\"]*. properties.txt) )
如果您要求bash告诉您此数组中存储了什么,您将得到以下响应:

$ declare -p arr
declare -a arr=([0]="\"user\"" [1]="\"jack\"" [2]="\"password\"" [3]="\"kilby\"" \
[4]="\"install\"" [5]="\"False\"" [6]="\"deploy\"" [7]="\"\"" \
[8]="\"build\"" [9]="\"123\"" [10]="\"ip\"" [11]="\"0.0.0.0\"")
请注意,我已经将var字段deploy:false修改为deploy:test我的答案——这是上面的arr[7]

我发现处理数组中缺少的字段的最简单方法是使用bash替换技术重新定义相同的arr数组,如下所示:

$ arr=( ${arr[@]//\"\"/\"empty\"/} )
$ declare -p arr
declare -a arr=([0]="\"user\"" [1]="\"jack\"" [2]="\"password\"" [3]="\"kilby\"" \ 
[4]="\"install\"" [5]="\"False\"" [6]="\"deploy\"" [7]="\"empty\"/" \
[8]="\"build\"" [9]="\"123\"" [10]="\"ip\"" [11]="\"0.0.0.0\"")
请注意,arr[7]已从以前更改为空

实际上,您的代码会将空字段的字符串\\存储到数组中,该字符串将由echo-like-simple打印

在我的替换之后,declare-p建议arr[7]=\empty\,这将由echo打印为simple empty。当然,您可以通过保持双引号的转义,将此文本更改为任何您喜欢的内容

第二个var2的结果={k1:,k2:,k3:}

注意: 此解决方案仅建议代码的下一步。我还没有测试过您的数据操作技术,例如grep等。

jq是从shell解析JSON的工具。您可以用其他语言python、php、ruby、GO等解析JSON,但如果您这样做的话,您也可以用这种语言编写整个程序

所以。。在bash中,您可以使用jq:

如果希望在bash 4+中的关联数组中包含这些对,可以执行以下操作:

$ declare -A a="( $(jq -r 'keys[] as $k | "[\($k)]=\"\(.[$k])\""' <<<"$var" ) )"
$ declare -p a
declare -A a=([build]="123" [install]="False" [ip]="0.0.0.0" [user]="jack" [deploy]="False" [password]="kilby" )
只要变量索引或值中没有换行符,这种方法就行。要使其处理更复杂的数据,您需要。。更复杂的处理程序。如果存在换行的风险,请在问题中提及。

此答案的解决方案将键值对读入规则数组的连续元素。元素0接收第一个键,元素1关联值,…,如问题所示;有关创建Bash v4+关联数组的解决方案,请参见

tl;博士:

仅使用标准实用程序: jq命令是:keys_unsorted确保按输入顺序枚举键,-r确保将结果作为原始值而不是JSON编码输出,在本例中,这意味着双引号被剥离

Bash v3.x等效版本:

arr=()
while IFS= read -r val; do
  arr+=( "$val" )
done < <(grep -o '"[^"]*.' properties.txt | tr -d \")
arr=()
while IFS= read -r val; do
  arr+=( "$val" )
done < <(jq -r 'keys_unsorted[] as $k | "\($k)\n\(.[$k])"' properties.txt)
第一件事:如果可行,使用合适的JSON解析器总是值得的,比如

您的方法存在的问题:

grep-o\[^\]*。在输出中包含封闭,数组赋值arr=。。。然后作为值的一部分进行解析

通过管道连接到tr-d\来删除它们,很容易解决这个问题,但是arr=$。。。然后,语法会忽略空字符串,因此在该过程中会丢失空输入值

也就是说,您通常应该避免arr=$,因为它 a总是从命令替换$分割输出。。。通过空格分词,无论嵌入的引号字符是什么,默认情况下,b都会将生成的单词进行文件名扩展

避免这两个问题的安全替代方案——至少对于面向行的输入——是使用readarray,自Bash v4.0以来就可用-t从读取的行中删除尾随的\n


在Bash v3.x中,必须使用while循环来读取行,因为几乎等同于readarray-t arr-IFS=$'\n'read-d-ra arr-的构造也会忽略空条目。

对于快速响应人员来说,这是一个很大的问题。我用下面的方法解决了我的问题

makeKeyValueArray (){
# remove colon and commas
IFS=':' read -ra ADDR <<< "$var"
IFS=',' read -ra ADDR2 <<< "${ADDR[@]}"

echo ${ADDR2[@]} > "$destdir"

#remove curly braces
sed 's/[{}]//g' $destdir > temp_ip_prop.txt
mv temp_ip_prop.txt $destdir



#store each item in a array "arr"
    cn=0;
        for i in `cat $destdir`
        do
        arr[$cn]=$i;
        ((cn=cn+1));
        done

}
然后在一个循环中,我比较了数组是否包含。如果是这样的话,我只是把那个字段作为空白

我犯的错误是在

arr=$grep-o\[^\]*。properties.txt

这是将每个\存储到阵列中

什么是欲望
d输出以及代码的输出是什么?您最好使用一种具有适当JSON解析器的语言;我不知道有任何这样的东西是用shell写的。@GeorgeVasiliou我只需要一个正则表达式,它可以将双引号中的所有字符串存储到数组中。如果某个键的值为empty@chepner好的,谢谢你的建议。如果不是包含有效JSON的文本文件,JSON文件是什么?非常感谢你的建议。我没有得到否决票的原因,但我想我知道。我的解决方案并不是抵制输入布局的微小变化,使用理解json的工具更好。我发布这个答案是为了帮助其他人阅读如何使用bash脚本将.txt文件中的所有键值对传输到数组而不使用json输入字符串的问题。非常感谢@peak@BeatrixKiddo我想您考虑过在bash-see中指定默认值之类的事情。这些技术在您的情况下不起作用,因为根据bash逻辑,您的条目不会被认为是空的。我解决了我的问题。谢谢你的投票,没有评论吗?妮茜!你不需要评估;如果p=build=123,那么declare$p将扩展为declare build=123,这将为build赋值123。@chepner-yep,我刚刚意识到,谢谢。修正了。事实上,我想您需要eval,以便引号作为declare命令declare$p的一部分使用。但是,jq返回的引号都不能保护for循环中的空格不被单词分割;您需要使用while循环对输出进行迭代,只有在没有任何值或键包含换行符的情况下,这种循环才会起作用。@chepner,我相信最后一个declare示例应该不会出现除换行符以外的任何内容。我可以接受是的,for循环确实存在问题,因此发出了警告。也许我应该把它删除。@chepner-removed,并在底部添加了更多的解释。凌晨2:30在我现在的位置,我明天可能会再看一遍。非常感谢@mklement。
$ var2='{"k1":"","k2":"","k3":""}'
$ echo "$var2" >properties.txt
$ cat properties.txt
{"k1":"","k2":"","k3":""}
$ arr=( $(grep -o \"[^\"]*. properties.txt) )
$ declare -p arr
declare -a arr=([0]="\"k1\"" [1]="\"\"" [2]="\"k2\"" [3]="\"\"" [4]="\"k3\"" [5]="\"\"")
$ arr=( ${arr[@]//\"\"/\"empty\"/} )
$ declare -p arr
declare -a arr=([0]="\"k1\"" [1]="\"empty\"/" [2]="\"k2\"" [3]="\"empty\"/" [4]="\"k3\"" [5]="\"empty\"/")
$ echo "${arr[@]}"
"k1" "empty"/ "k2" "empty"/ "k3" "empty"/
$ jq 'keys[] as $k | "\($k)=\(.[$k])"' <<<"$var" 
"build=123"
"deploy=False"
"install=False"
"ip=0.0.0.0"
"password=kilby"
"user=jack"
$ declare -A a="( $(jq -r 'keys[] as $k | "[\($k)]=\"\(.[$k])\""' <<<"$var" ) )"
$ declare -p a
declare -A a=([build]="123" [install]="False" [ip]="0.0.0.0" [user]="jack" [deploy]="False" [password]="kilby" )
readarray -t arr < <(grep -o '"[^"]*.' properties.txt | tr -d \")
arr=()
while IFS= read -r val; do
  arr+=( "$val" )
done < <(grep -o '"[^"]*.' properties.txt | tr -d \")
readarray -t arr < <(jq -r 'keys_unsorted[] as $k | $k, .[$k]' properties.txt)
arr=()
while IFS= read -r val; do
  arr+=( "$val" )
done < <(jq -r 'keys_unsorted[] as $k | "\($k)\n\(.[$k])"' properties.txt)
makeKeyValueArray (){
# remove colon and commas
IFS=':' read -ra ADDR <<< "$var"
IFS=',' read -ra ADDR2 <<< "${ADDR[@]}"

echo ${ADDR2[@]} > "$destdir"

#remove curly braces
sed 's/[{}]//g' $destdir > temp_ip_prop.txt
mv temp_ip_prop.txt $destdir



#store each item in a array "arr"
    cn=0;
        for i in `cat $destdir`
        do
        arr[$cn]=$i;
        ((cn=cn+1));
        done

}