简体   繁体   中英

How to read function names from file and prefix file with said function names in Bash effectively?

I have a bunch of files which I concatenate into one large file. The single large file then looks like this:

function foo() {
  // ... implementation
}

function bar() {
  // ... implementation
}

function baz() {
  // ... implementation
}

function foo_bar() {
  // ... implementation
}

...

A bunch of functions. I want to create a new file with all this content, PLUS prefixing it with this:

module.exports = {
  foo,
  bar,
  baz,
  foo_bar,
  ...
}

Basically exporting every function. What is the most simple, cleanest way I can do this in bash?

As far as I got is this haha, it is really confusing to try and come up with a solution:

A := out/a.js
B := out/b.js

all: $(A) $(B)

$(A):
  @find src -name '*.js' -exec cat {} + > $@

$(B):
  @cat out/a.js | grep -oP '(?function )[a-zA-Z0-9_]+(? \{)'

.PHONY: all

这个简单的awk脚本可以做到

awk -F '( |\\()' 'BEGIN {print "module.exports = {"} /function/ {print "\t" $2 ","} END {print "}"}' largefile.js

Store the list of functions declared before and after sourcing the file. Compute the difference. You can get the list of currently declared functions with declare -F .

A() { :; }
pre=$(declare -F | sed 's/^declare -f //')

function foo() {
  // ... implementation
}

function bar() {
  // ... implementation
}

function baz() {
  // ... implementation
}

function foo_bar() {
  // ... implementation
}

post=$(declare -F | sed 's/^declare -f //')

diff=$(comm -13 <(sort <<<"$pre") <(sort <<<"$post"))

echo "module.exports = {
    $(<<<"$diff" paste -sd, | sed 's/,/,\n\t/g')
}"

I think with bash --norc you should get a clean environment, so with bash --norc -c 'source yourfile.txt; declare -F' bash --norc -c 'source yourfile.txt; declare -F' you could get away with computing the difference:

cat <<EOF >yourfile.txt
function foo() {
  // ... implementation
}

function bar() {
  // ... implementation
}

function baz() {
  // ... implementation
}

function foo_bar() {
  // ... implementation
}
EOF

diff=$(bash --norc -c 'source yourfile.txt; declare -F' | cut -d' ' -f3-)

echo "module.exports = {
    $(<<<"$diff" paste -sd, | sed 's/,/,\n\t/g')
}"

Both code snippets should output:

module.exports = {
    bar,
    baz,
    foo,
    foo_bar
}

Note: the function name() {} is a mix of ksh and posix form of function definition - the ksh uses function name {} while posix uses name() {} . Bash supports both forms and also the strange mix of both forms. To be portable, just use the posix version name() {} . More info maybe at wiki-deb-bash-hackers.org obsolete and deprecated syntax .

You could use echo and sed :

echo 'modules.exports = {'; sed -n 's/^function \([^(]*\)(.*/  \1,/p' input.txt; echo '}'

result:

modules.exports = {
  foo,
  bar,
  baz,
  foo_bar,
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM