我有一个 json 文件:
...
...
"dependencies": {
// more lines
},
"exports": {
"./package.json": "./package.json",
"./.DS_Store": "./.DS_Store",
"./accordions/AccordionDefault.svelte": "./accordions/AccordionDefault.svelte",
".": "./index.js",
"./modals/modalStores": "./modals/modalStores.js",
// more lines
"./tabs/DefaultTabs.svelte": "./tabs/DefaultTabs.svelte",
"./tabs/InteractiveTabs.svelte": "./tabs/InteractiveTabs.svelte",
"./tabs/PillTabs.svelte": "./tabs/PillTabs.svelte"
},
"svelte": "./index.js"
}
我可以使用以下命令提取所有导出jq
:
cat './node_modules/module_name/package.json'| jq '.exports'
{
"./package.json": "./package.json",
"./.DS_Store": "./.DS_Store",
"./accordions/AccordionDefault.svelte": "./accordions/AccordionDefault.svelte",
"./accordions/AccordionItem.svelte": "./accordions/AccordionItem.svelte",
"./alerts/Alert.svelte": "./alerts/Alert.svelte",
...
}
我想提取文件名及其文件路径(忽略前两行),仅用于精简文件:
// using my_command ls to overwrite the output to my_file
my_command ls
// outputting the my_file
cat my_file
AccordionDefault ./accordions/AccordionDefault.svelte
AccordionItem ./accordions/AccordionItem.svelte
...
我该如何使用 Shell/Bash 脚本?
答案1
假设“文件名”的意思类似于应用于对象basename NAME EXT
的键exports
:
$ jq -r '.exports | to_entries[] |
{ name: ((.key / "/")[-1] / ".svelte")[0], path: .value } | [ .name, .path ] | @tsv
' ./node_modules/module_name/package.json
package.json ./package.json
.DS_Store ./.DS_Store
AccordionDefault ./accordions/AccordionDefault.svelte
DefaultTabs ./tabs/DefaultTabs.svelte
InteractiveTabs ./tabs/InteractiveTabs.svelte
PillTabs ./tabs/PillTabs.svelte
这使用字符串“division”来分割键,/
然后再次分割.svelte
(您也可以在此处使用 jqsplit
函数)。
如果您想跳过“前两个”条目,请替换to_entries[]
为to_entries[2:][]
- 但据我所知,JSON 对象中的键值对并未真正排序,因此根据其他标准选择条目会更加稳健,例如.key | endswith(".svelte")
:
$ jq -r '.exports | to_entries[] | select(.key | endswith(".svelte")) |
{ name: ((.key / "/")[-1] / ".svelte")[0], path: .value } | [ .name, .path ] | @tsv
' package.json
AccordionDefault ./accordions/AccordionDefault.svelte
DefaultTabs ./tabs/DefaultTabs.svelte
InteractiveTabs ./tabs/InteractiveTabs.svelte
PillTabs ./tabs/PillTabs.svelte
答案2
下面将查找包含子目录或一组 2 个斜杠的行(/.*/.*:)
,这样它只会处理 jq 提供的其他行,因此:
jq '.exports' ./node_modules/module_name/package.json|awk '/\/.*\/.*:/{
gsub(/"/,"",$0)
gsub(/,$/,"",$0)
nf=split ($0,array,":")
ni=split (array[1],subarray,"/")
print subarray[ni],array[2]
}'>my_file
这是将提供的输出:
AccordionDefault.svelte ./accordions/AccordionDefault.svelte
DefaultTabs.svelte ./tabs/DefaultTabs.svelte
InteractiveTabs.svelte ./tabs/InteractiveTabs.svelte
PillTabs.svelte ./tabs/PillTabs.svelte
华泰
PS,根据要求,为了提取另一个模式,只需将当前的模式更改/\/.*\/.*:/
为所需的模式,在 svelte 的情况下,如果/svelte/
您正在寻找整个单词,则必须使用类似 `/< svelte>/,其中尖括号指示正则表达式作为单词的开头和结尾,在这种情况下,诸如“esveltex”、“esvelte”、“sveltetc”之类的内容将不会显示,因为即使包括搜索字符串,这是不是单词的开头,也不是单词的结尾。
经过测试:
jq '.exports' ./node_modules/module_name/package.json|awk '/\<svelte\>/{
gsub(/"/,"",$0)
gsub(/,$/,"",$0)
nf=split ($0,array,":")
ni=split (array[1],subarray,"/")
print subarray[ni],array[2]
}'
AccordionDefault.svelte ./accordions/AccordionDefault.svelte
DefaultTabs.svelte ./tabs/DefaultTabs.svelte
InteractiveTabs.svelte ./tabs/InteractiveTabs.svelte
PillTabs.svelte ./tabs/PillTabs.svelte
华泰
答案3
执行此操作的更好工具是 jp,它是 jmespath 的缩写。并非所有发行版存储库都可用,但您可以在此处获取:https://jmespath.org/。
解决方案:
$ cat minimal.json
{
"x": {
"./package.json": "./package.json",
"./.DS_Store": "./.DS_Store",
"./accordions/AccordionDefault.svelte": "./accordions/AccordionDefault.svelte",
"./accordions/AccordionItem.svelte": "./accordions/AccordionItem.svelte",
"./alerts/Alert.svelte": "./alerts/Alert.svelte"
}
}
$ cat minimal.json | jp "x.values(@)"
[
"./accordions/AccordionItem.svelte",
"./alerts/Alert.svelte",
"./package.json",
"./.DS_Store",
"./accordions/AccordionDefault.svelte"
]