How do you construct a grep & command to match a number of patterns depending on how many are provided at runtime?
You can leverage the printf
builtin.
mo1 () {
for file in *.txt; do
grep -n -C1 "$(printf "%s.*" "$@")" "$file"
done
}
This simple version inserts .*
after the last element. It doesn't matter for this specific use case, but in other cases (e.g. grep -o
) you may need to strip off the extra .*
at the end.
mo1 () {
pattern=$(printf "%s.*" "$@")
pattern=${pattern%??}
for file in *.txt; do
grep -n -C1 "$pattern" "$file"
done
}
In bash, you can put the printf
output directly in a variable, which is slightly faster than using a command substitution (but this is unlikely to ever matter, even on Cygwin where subshells are slow).
mo1 () {
printf -v pattern "%s.*" "$@"
pattern=${pattern%??}
for file in *.txt; do
grep -n -C1 "$pattern" "$file"
done
}
If you wanted to insert a single character between the positional parameters, you could set IFS
to that character and use "$@"
. But that doesn't work if the separator is more than one character. In ksh and bash, if there's a character that doesn't appear in the pattern, you can use that for joining and then perform a replacement. For example, here, it wouldn't make sense for patterns to contain newlines, so:
mo1 () {
typeset IFS=$'\n'
typeset pattern="$*"
pattern=${pattern//$'\n'/.*}
for file in *.txt; do
grep -n -C1 "$pattern" "$file"
done
}
In zsh, of course, there's a direct way.
mo1 () {
for file in *.txt; do
grep -n -C1 ${(j:.*:)@} $file
done
}