Asked  7 Months ago    Answers:  5   Viewed   26 times
#!/bin/sh
for i in {1..5}
do
   echo "Welcome"
done

Would work, displays Welcome 5 times.

#!/bin/sh
howmany=`grep -c $1 /root/file`
for i in {1..$howmany}
do
   echo "Welcome"
done

Doesn't work! howmany would equal 5 as that is what the output of grep -c would display. $1 is parameter 1 which is specific when running the script.

Any ideas?

 Answers

79

create a sequence to control your loop

for i in $(seq 1 $howmany); do
echo "Welcome";
done
Tuesday, June 1, 2021
 
Jeff
answered 7 Months ago
96

Why

When the string is expanded, it is split into words, but it is not re-evaluated to find special characters such as quotes or dollar signs or ... This is the way the shell has 'always' behaved, since the Bourne shell back in 1978 or thereabouts.

Fix

In bash, use an array to hold the arguments:

argumentArray=(-ir 'hello world')
grep "${argumentArray[@]}" .

Or, if brave/foolhardy, use eval:

argumentString="-ir 'hello world'"
eval "grep $argumentString ."

On the other hand, discretion is often the better part of valour, and working with eval is a place where discretion is better than bravery. If you are not completely in control of the string that is eval'd (if there's any user input in the command string that has not been rigorously validated), then you are opening yourself to potentially serious problems.

Note that the sequence of expansions for Bash is described in Shell Expansions in the GNU Bash manual. Note in particular sections 3.5.3 Shell Parameter Expansion, 3.5.7 Word Splitting, and 3.5.9 Quote Removal.

Tuesday, June 1, 2021
 
etsous
answered 7 Months ago
49

bash does brace expansion before variable expansion, so you get weekly.{0..4}.
Because the result is predictable and safe(Don't trust user input), you can use eval in your case:

$ WEEKS_TO_SAVE=4
$ eval "mkdir -p weekly.{0..$((WEEKS_TO_SAVE))}"

note:

  1. eval is evil
  2. use eval carefully

Here, $((..)) is used to force the variable to be evaluated as an integer expression.

Tuesday, June 1, 2021
 
michele
answered 7 Months ago
51

This takes the variable branch_name, if it is defined. If it is not defined, use HEAD instead.

See Shell Parameter Expansion for details:

3.5.3 Shell Parameter Expansion

The ‘$’ character introduces parameter expansion, command substitution, or arithmetic expansion. ... The basic form of parameter expansion is ${parameter}.
...
When not performing substring expansion, using the form described below (e.g., ‘:-’), Bash tests for a parameter that is unset or null. Omitting the colon results in a test only for a parameter that is unset. Put another way, if the colon is included, the operator tests for both parameter’s existence and that its value is not null; if the colon is omitted, the operator tests only for existence.

${parameter:-word}

If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.


Substrings are covered a few lines below. The difference between the two is

${parameter:-word}

vs

${parameter:offset}
${parameter:offset:length}

${parameter:offset}
${parameter:offset:length}

This is referred to as Substring Expansion. It expands to up to length characters of the value of parameter starting at the character specified by offset.
...
If offset evaluates to a number less than zero, the value is used as an offset in characters from the end of the value of parameter. ... Note that a negative offset must be separated from the colon by at least one space to avoid being confused with the ‘:-’ expansion.

Sunday, August 8, 2021
 
Sendy
answered 4 Months ago
44

The short answer is echo bunny(seq 6)

Longer answer: In keeping with fish's philosophy of replacing magical syntax with concrete commands, we should hunt for a Unix command that substitutes for the syntactic construct {1..6}. seq fits the bill; it outputs numbers in some range, and in this case, integers from 1 to 6. fish (to its shame) omits a help page for seq, but it is a standard Unix/Linux command.

Once we have found such a command, we can leverage command substitutions. The command (foo)bar performs command substitution, expanding foo into an array, and may result in multiple arguments. Each argument has 'bar' appended.

Monday, August 9, 2021
 
vivek
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share