0

I have a json file:

...
...
  "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"
}

I can extract all exports using 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",
...
}

I'd like to extract the file names and its paths to a file (ignoring the first 2 lines) for only svelte files:

// 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
...

How can I do using Shell/Bash script?

3 Answers 3

2

Assuming by "the file names" you mean something akin to applying basename NAME EXT on the keys of the exports objects:

$ 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

This uses string "division" to split the keys on / then again on .svelte (you could also use the jq split function here).

If you want to skip "the first two" entries, replace to_entries[] with to_entries[2:][] - but AFAIK key-value pairs in a JSON object are not really ordered so it would be more robust to select entries based on some other criterion, such as .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
1

The following will look for lines containing subdirectories or a set of 2 slashes (/.*/.*:), in this way it'll only treat the other lines provided by jq, hence:

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

This is the output that will be provided:

AccordionDefault.svelte  ./accordions/AccordionDefault.svelte
DefaultTabs.svelte  ./tabs/DefaultTabs.svelte
InteractiveTabs.svelte  ./tabs/InteractiveTabs.svelte
PillTabs.svelte  ./tabs/PillTabs.svelte

HTH

PS, as requested, in order to extract another pattern just change the pattern that currently is /\/.*\/.*:/ to the desired, in the case of svelte, it will be /svelte/ if you are looking for a whole word you will have to use something like this `/<svelte>/, where the angular brackets instruct the regular expression as the beginning and ending of the word, in this case something like "esveltex", "esvelte", "sveltetc" willl not be shown, since even includingthe search string, this is not the beginning, neither the end of the word.

Following a test:

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

HTH

2
  • Thank you for your answer. I just updated my question. I'd like extract lines contain svelte. There is one line with js file. How can I modify /\/.*\/.* to adopt extract only svelte files?
    – shin
    Mar 19 at 21:21
  • shin, I've just complemented the answer, according to your requirement. Mar 19 at 22:47
0

The better tool to do this is jp, short for jmespath. Not available on all distro repositories but you can get it here: https://jmespath.org/.

The solution:

$ 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"
]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.