Bash/awk extract function from file.
I'm trying to write a one liner that can extract a certain bash function from a file. This code will extract the function test() from test.sh:
Code:
cat test.sh | awk '/test()/ {start=1} /{/ {if (start == 1) { line=$0; while(sub("{", "", line)) brackets++}} /}/ {if (start == 1) { line2=$0; while(sub("}", "", line2)) brackets--}} {if (start == 1) if (brackets > 0) print $0; else { print; exit}}' Edit: "perfectly fine" is not necessarily correct, commented brackets will still get counted. |
Welll... it won't handle the case where the brace ("{") may be inside quotes...
|
personally I use sed for things like this
Code:
sed '/test()/,/^}$/!d' Infile |
Quote:
Quote:
|
Quote:
Code:
mkdir Wtf |
@Firerat: That won't work with functions like
Code:
function x { Code:
function x { true; } Edit: Oh yes your code could work with functions made of regular format but some do this: Code:
function x { Code:
if tests; do Code:
function x { |
From a language exclusive point of view I would suggest counting the braces and once you have a match for left and right count, assuming the code has a working function without errors,
you should be at the end of your function. As konsolebox has pointed out, there are several different formats you may need to contend with to have the count correct :) |
So had a quick think about it, this is the sort of thing I would look at:
Code:
ruby -ne 'BEGIN{l=r=0};if $_ =~ /test/; until l > 0 && l == r; l+=$_.scan(/{/).size;r+=$_.scan(/}/).size;print $_;gets;end;break;end' file |
Quote:
|
Fixed my original with awk:
Code:
cat test.sh | awk -v sq="'" '/test()/ {line=$0; gsub("\"[^\"]*\"", "", line); gsub(sq"[^"sq"]*"sq, "", line); gsub("#.*$", "", line); if( sub("test()", "", line) ) {start=1; brackets=0}} /function test/ {line=$0; gsub("\"[^\"]*\"", "", line); gsub(sq"[^"sq"]*"sq, "", line); gsub("#.*$", "", line); if( sub("test()", "", line) ) {start=1; brackets=0}} /{/ {if (start == 1) { line=$0; gsub("\"[^\"]*\"", "", line); gsub(sq"[^"sq"]*"sq, "", line); gsub("#.*$", "", line); while(sub("{", "", line)) { brackets++ }}} /}/ {if (start == 1) { line2=$0; gsub("\"[^\"]*\"", "", line); gsub(sq"[^"sq"]*"sq, "", line); gsub("#.*$", "", line); while(sub("}", "", line2)) brackets--}} {if (start == 1) if (brackets > 0) print $0" - "brackets; else { print $0" - "brackets" - EXITING"; exit}}' I think Code:
gsub("\"[^\"]*\"", "", line); gsub(sq"[^"sq"]*"sq, "", line); gsub("#.*$", "", line); |
That should work nearly all the time. The most unusual cases will be where the braces are escaped (happens with find commands, and xargs).
|
I'll code this out later today, but would:
1. Removing everything inside backticks and $() 2. Removing all occurences of \{ and \} cover all cases? Is there any other way to escape a bracket? Edit: I'll also have to remove escaped quotes before I remove strings, too. |
Only remaining problem would be typeos in the file... These could cause problems with counting (missing quote, done keyword, close paren...). These don't HAVE to be detected by the shell defining the functions... until the function is actually invoked. But they could cause problems for the scanner.
BTW, as for other ways of escaping--- yes. "here" documents are another... |
Dang, forgot about those. Also, I'm not going to worry about typos, if it's broken then it'll break hard. Heredocs on the other hand...
Edit: If there's no other way to escape from a heredoc other than the specified string on a line by itself, it may not be that bad after all. |
You should also consider that awk process texts generally line by line and not character by character unlike other languages. Example is my attempt to parse scripts like this. It works and is made complex, but is still limited.
compiler.gawk |
All times are GMT -5. The time now is 09:51 AM. |