如何使用 Shell/Bash 脚本提取单词

如何使用 Shell/Bash 脚本提取单词

我有一个 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"
]

相关内容