Regex 使用bash脚本将IANA向后文件转换为json文件 什么

Regex 使用bash脚本将IANA向后文件转换为json文件 什么,regex,bash,shell,sed,Regex,Bash,Shell,Sed,我想将转换为具有唯一键的json文件,但为了做到这一点,我必须确保键成为值,反之亦然 这是因为json文件不能有重复的密钥 例子: 该文件包含大量重复链接,但在本例中,让我们使用以下两个: Link America/Toronto America/Montreal Link America/Toronto Canada/Eastern 我想把它们变成: “美国/蒙特利尔”:“美国/多伦多”, “加拿大/东部”:“美洲/多伦多” 这样他们都能输出多伦多 到目前为止,我

我想将转换为具有唯一键的json文件,但为了做到这一点,我必须确保键成为值,反之亦然

这是因为json文件不能有重复的密钥

例子: 该文件包含大量重复链接,但在本例中,让我们使用以下两个:

Link    America/Toronto     America/Montreal
Link    America/Toronto     Canada/Eastern
我想把它们变成:

“美国/蒙特利尔”:“美国/多伦多”, “加拿大/东部”:“美洲/多伦多”

这样他们都能输出多伦多

到目前为止,我所尝试的: 到目前为止,我制作的正则表达式是:

  • 搜索:
    ^Link[\s]*([a-zA-Z\/\-]*)[\s]*([a-zA-Z\/\-]*)$
  • 替换为:
    “\2”:“\1”,
最后我试着用sed这样做:
sed-E的链接[\s]*([a-zA-Z\/\-]*)[\s]*([a-zA-Z\/\-]*)$|“\2:“\1”|”。/向后

但出于某种原因,它一直输出整个文件,而不替换任何内容


我做错了什么?

我强烈建议使用
jq
,这是一个基于JSON构建的工具(因此,与
sed
不同,它无法生成无效的JSON输出,除非明确指向)

以下内容是为了便于阅读而不是简洁:

input='
Link    America/Toronto     America/Montreal
Link    America/Toronto     Canada/Eastern
'

# -R == raw input; -n == don't consume input until directed by "input" or "inputs"
jq -Rn '
# start by creating an array of smaller arrays, one per line
[inputs
 | select((. | length) > 1)    ## ignore empty lines
 | split("[[:space:]]+"; "")   ## Split on runs of whitespace
 | select(.[0] == "Link")]     ## Ignore anywhere first column is not "Link"
# then combine those smaller arrays to create key/value pairs in one big object
| reduce .[] as $item ({}; .[$item[2]]=$item[1])
' <<<"$input"
…正如你在


或者,使用Python编写相同的逻辑(包装为从shell调用):

#通过引用的代码在变量中捕获Python代码
#这允许它作为文本包含在shell脚本中

link2json_py=$(cat我强烈建议使用
jq
,这是一个基于JSON构建的工具(因此,与
sed
不同,除非明确指示,否则无法生成无效JSON的输出)

以下内容是为了便于阅读而不是简洁:

input='
Link    America/Toronto     America/Montreal
Link    America/Toronto     Canada/Eastern
'

# -R == raw input; -n == don't consume input until directed by "input" or "inputs"
jq -Rn '
# start by creating an array of smaller arrays, one per line
[inputs
 | select((. | length) > 1)    ## ignore empty lines
 | split("[[:space:]]+"; "")   ## Split on runs of whitespace
 | select(.[0] == "Link")]     ## Ignore anywhere first column is not "Link"
# then combine those smaller arrays to create key/value pairs in one big object
| reduce .[] as $item ({}; .[$item[2]]=$item[1])
' <<<"$input"
…正如你在


或者,使用Python编写相同的逻辑(包装为从shell调用):

#通过引用的代码在变量中捕获Python代码
#这允许它作为文本包含在shell脚本中

link2json_py=$(cat我假设您使用的是GNU sed。您的问题来自GNU扩展正则表达式的特殊性,不幸的是,这些表达式没有很好的文档记录。例如:

速记 类
\w
\w
\s
\s
可以用来代替
[:alnum:][/code>,
[^[:alnum:]
[[:space:]
[^[:space:]
。您可以使用这些 直接在正则表达式中,但不在括号表达式中。反斜杠 括号内的表达式始终是一个文本

因此,您不能在
[…]
集合定义中使用
\s
的缩写
[:space:][/code>。正如所述,您不需要集合定义和:

sed -E 's|^Link\s*([a-zA-Z\/\-]*)\s*([a-zA-Z\/\-]*)$|"\2" : "\1"|' ./backward
应该有效。如果出于任何原因,您希望使用集合定义

sed -E 's|^Link[[:space:]]*([a-zA-Z\/\-]*)[[:space:]]*([a-zA-Z\/\-]*)$|"\2" : "\1"|' ./backward
也应该有效。请注意:

 sed -E 's|^Link\s+([a-zA-Z\/\-]+)\s+([a-zA-Z\/\-]+)$|"\2" : "\1"|' ./backward
可能更好。而且:

 sed -E 's|^Link\s+([[:alpha:]/-]*)\s+([[:alpha:]/-]*)$|"\2" : "\1"|' ./backward

更好。

我假设您使用的是GNU sed。您的问题来自于GNU扩展正则表达式的特殊性,不幸的是,这些表达式没有很好的文档记录。例如:

速记 类
\w
\w
\s
\s
可以用来代替
[:alnum:][/code>,
[^[:alnum:]
[[:space:]
[^[:space:]
。您可以使用这些 直接在正则表达式中,但不在括号表达式中。反斜杠 括号内的表达式始终是一个文本

因此,您不能在
[…]
集合定义中使用
\s
的缩写
[:space:][/code>。正如所述,您不需要集合定义和:

sed -E 's|^Link\s*([a-zA-Z\/\-]*)\s*([a-zA-Z\/\-]*)$|"\2" : "\1"|' ./backward
应该有效。如果出于任何原因,您希望使用集合定义

sed -E 's|^Link[[:space:]]*([a-zA-Z\/\-]*)[[:space:]]*([a-zA-Z\/\-]*)$|"\2" : "\1"|' ./backward
也应该有效。请注意:

 sed -E 's|^Link\s+([a-zA-Z\/\-]+)\s+([a-zA-Z\/\-]+)$|"\2" : "\1"|' ./backward
可能更好。而且:

 sed -E 's|^Link\s+([[:alpha:]/-]*)\s+([[:alpha:]/-]*)$|"\2" : "\1"|' ./backward
更好。

解决方案: 我的问题的答案解决方案是以下命令:

sed-En的|^链接[:space:][]*([^[:space:][]*)[:space:][]*([^[:space:][]*)$|“\2:“\1”| p./向后

它按预期工作,并创建JSON输出的主体

TL/DR: 具体来说,雷诺的回答让我意识到我必须使用
[[:space:]
而不是
[/s]

在运行他的命令后,我留下了几行不需要的行:

A)文件顶部包含的注释

i、 e
#此文件是…

(通过在脚本的开头添加
-n
标志和结尾添加
p
标志,告诉sed
不要打印不匹配的行(发现不匹配的行),解决了这个问题) 及

B)某些未转换的行

i、 e
Link太平洋/Pago_帕果太平洋/Samoa

(这是通过告诉
sed
匹配组
[^[:space:]
中任何非空格的内容来解决的)

最后,整个脚本: 看起来像这样:

#!/bin/bash
echo "{";
sed -En 's|^Link[[:space:]]*([^[:space:]]*)[[:space:]]*([^[:space:]]*)$|    "\2": "\1"|p' ./backward
echo "}";
然后像这样运行脚本:
sh index.sh>timezones.json
输出一个漂亮的json文件。

解决方案: 我的问题的答案解决方案是以下命令:

sed-En的|^链接[:space:][]*([^[:space:][]*)[:space:][]*([^[:space:][]*)$|“\2:“\1”| p./向后

它按预期工作,并创建JSON输出的主体

TL/DR: 具体来说,雷诺的回答让我意识到我必须使用
[[:space:]
而不是
[/s]

在运行他的命令后,我留下了几行不需要的行:

A)文件顶部包含的注释

i、 e
#此文件是…

(通过在脚本的开头添加
-n
标志和结尾添加
p
标志,告诉sed
不要打印不匹配的行(发现不匹配的行),解决了这个问题) 和