4
\$\begingroup\$

I'm writing a bash script to search C source files and find the lines where I missed the void keyword (unlike in C++, in C, empty parameter lists have to be indicated with the void keyword).

I read that I shouldn't use for but while: https://mywiki.wooledge.org/DontReadLinesWithFor

I find that for has an easier to follow, top-down structure (first I write the command that produces the items to be iterated, then I write what to do with each).

I understand that if a filename contained a newline it would cause trouble in case of for; however, with IFS=$'\n'; set -f I would think all other problems are solved.

My code using for:

#!/bin/bash
returnTypeOpt_BRE='\([a-zA-Z_][a-zA-Z0-9_]\{0,\}[* ]\{1,\}\)\{0,1\}'
spaceOpt_BRE=$'[ \t\r]\\{0,\\}'
functionName_BRE='\([a-zA-Z_][a-zA-Z0-9_]\{0,\}\)'
declarationMissingVoid_BRE="^$returnTypeOpt_BRE$spaceOpt_BRE$functionName_BRE$spaceOpt_BRE($spaceOpt_BRE)$spaceOpt_BRE;$spaceOpt_BRE\$"
targetFolder_Path="1ドル"
if [ $# -eq 0 ]; then
 targetFolder_Path="."
fi
IFS=$'\n'; set -f; for file in $( find "$targetFolder_Path" -name '*.c' -or -name '*.h' ); do
 printf "%s\n" "$file"
 for line in $( grep --basic-regex --regexp=$declarationMissingVoid_BRE $file ); do
 printf "\t>%s\n" "$line"
 done
done; unset IFS; set +f

My code using while:

#!/bin/bash
returnTypeOpt_BRE='\([a-zA-Z_][a-zA-Z0-9_]\{0,\}[* ]\{1,\}\)\{0,1\}'
spaceOpt_BRE=$'[ \t\r]\\{0,\\}'
functionName_BRE='\([a-zA-Z_][a-zA-Z0-9_]\{0,\}\)'
declarationMissingVoid_BRE="^$returnTypeOpt_BRE$spaceOpt_BRE$functionName_BRE$spaceOpt_BRE($spaceOpt_BRE)$spaceOpt_BRE;$spaceOpt_BRE\$"
targetFolder_Path="1ドル"
if [ $# -eq 0 ]; then
 targetFolder_Path="."
fi
while IFS=; read -u 3 -r -d $'0円' file; do
 printf "%s\n" "$file"
 while IFS=; read -u 4 -r line; do
 printf "\t>%s\n" "$line"
 done 4< <( grep --basic-regex --regexp=$declarationMissingVoid_BRE $file )
done 3< <( find "$targetFolder_Path" -name '*.c' -print0 -or -name '*.h' -print0 )

So, for me both scripts work correctly, and produce the same result.

Beyond the "filenames with newlines" issue is there anything else that would make while better? Can you show me a test case?

If I had to solve similar but different (possibly more complex) tasks would I have problems with for?

AlexV
7,3532 gold badges24 silver badges47 bronze badges
asked Mar 11, 2020 at 11:17
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I'm writing a bash script to search C source files and find the lines where I missed the void keyword

This alone suggests that your approach is very problematic. To do this properly you'd effectively need to write most of a C parser, and that isn't a good use of your time. There are other approaches that would get you more mileage and accuracy:

  • Double-check that your compiler (gcc?) for sure doesn't have warnings that cover your use-case; if it does, then simply compile and look at the output.
  • Failing that, reuse a parser. I recommend the Clang AST.

Bash is just the hideously wrong tool for this. Save yourself the pain of writing regexes that are both complex and likely missing many edge cases.

answered Mar 15, 2020 at 13:50
\$\endgroup\$
2
  • \$\begingroup\$ GCC doesn't have warnings for this. If it did, that would be great, but it doesn't. \$\endgroup\$ Commented Mar 15, 2020 at 17:25
  • \$\begingroup\$ My C source files are quite simple, and I'm not afraid of missing some edge cases. On the other hand, I would like to know how to search regex patterns in multiple files with bash scripts. \$\endgroup\$ Commented Mar 15, 2020 at 18:35

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.