How do you construct a grep & command to match a number of patterns depending on how many are provided at runtime?
Clash Royale CLAN TAG#URR8PPP
I have exported some MS Word documents to plain text and use this function to parse the contents of the .txt
files in the current directory:
mo1 ()
for i in *.txt; do
echo "File: $i"
grep -n -HC 1 "$@" "$i"
done
If I had more than one pattern to look for, I could do mo1 | grep pattern2
. But what if I want to do something the result of which would be like grep -E 'pattern1.*pattern2[.*...]...'
depending on how many patterns are supplied to the function at runtime i.e. mo1 pattern1 pattern2 [...]
etc.? I can see the @
array could provide the number of items and I could construct over a loop a variable (finalpattern='$1.*$2.*$3') that would end up being the expression used for grep
. But I can't think of how to abstract that bit where you craft the expression in the function? Or is there a better/simpler way to do something like this?
shell-script grep
add a comment |
I have exported some MS Word documents to plain text and use this function to parse the contents of the .txt
files in the current directory:
mo1 ()
for i in *.txt; do
echo "File: $i"
grep -n -HC 1 "$@" "$i"
done
If I had more than one pattern to look for, I could do mo1 | grep pattern2
. But what if I want to do something the result of which would be like grep -E 'pattern1.*pattern2[.*...]...'
depending on how many patterns are supplied to the function at runtime i.e. mo1 pattern1 pattern2 [...]
etc.? I can see the @
array could provide the number of items and I could construct over a loop a variable (finalpattern='$1.*$2.*$3') that would end up being the expression used for grep
. But I can't think of how to abstract that bit where you craft the expression in the function? Or is there a better/simpler way to do something like this?
shell-script grep
add a comment |
I have exported some MS Word documents to plain text and use this function to parse the contents of the .txt
files in the current directory:
mo1 ()
for i in *.txt; do
echo "File: $i"
grep -n -HC 1 "$@" "$i"
done
If I had more than one pattern to look for, I could do mo1 | grep pattern2
. But what if I want to do something the result of which would be like grep -E 'pattern1.*pattern2[.*...]...'
depending on how many patterns are supplied to the function at runtime i.e. mo1 pattern1 pattern2 [...]
etc.? I can see the @
array could provide the number of items and I could construct over a loop a variable (finalpattern='$1.*$2.*$3') that would end up being the expression used for grep
. But I can't think of how to abstract that bit where you craft the expression in the function? Or is there a better/simpler way to do something like this?
shell-script grep
I have exported some MS Word documents to plain text and use this function to parse the contents of the .txt
files in the current directory:
mo1 ()
for i in *.txt; do
echo "File: $i"
grep -n -HC 1 "$@" "$i"
done
If I had more than one pattern to look for, I could do mo1 | grep pattern2
. But what if I want to do something the result of which would be like grep -E 'pattern1.*pattern2[.*...]...'
depending on how many patterns are supplied to the function at runtime i.e. mo1 pattern1 pattern2 [...]
etc.? I can see the @
array could provide the number of items and I could construct over a loop a variable (finalpattern='$1.*$2.*$3') that would end up being the expression used for grep
. But I can't think of how to abstract that bit where you craft the expression in the function? Or is there a better/simpler way to do something like this?
shell-script grep
shell-script grep
asked Jul 17 '14 at 22:47
jus cogens primejus cogens prime
2,70693067
2,70693067
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
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
Thank you for all the insight!! I think with the first one, I get some interaction because of C1, as if the output lines are context lines of the lines that contained the patterns, whereas they don't themselves contain it - at least I had that with the 3 terms I used for trying out the solutions. Otherwise this works flawlessly and will be very useful, thanks again!
– jus cogens prime
Jul 18 '14 at 3:30
add a comment |
Alternatively, you can use the --file
option to grep:
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file contains
zero patterns, and therefore matches nothing. (-f is specified by POSIX.)
Thanks! The idea is interesting but when you create such a pattern file it's really doing OR i.e. it will find lines with either patterns from that pattern file...
– jus cogens prime
Jul 18 '14 at 9:52
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f145196%2fhow-do-you-construct-a-grep-command-to-match-a-number-of-patterns-depending-on%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
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
Thank you for all the insight!! I think with the first one, I get some interaction because of C1, as if the output lines are context lines of the lines that contained the patterns, whereas they don't themselves contain it - at least I had that with the 3 terms I used for trying out the solutions. Otherwise this works flawlessly and will be very useful, thanks again!
– jus cogens prime
Jul 18 '14 at 3:30
add a comment |
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
Thank you for all the insight!! I think with the first one, I get some interaction because of C1, as if the output lines are context lines of the lines that contained the patterns, whereas they don't themselves contain it - at least I had that with the 3 terms I used for trying out the solutions. Otherwise this works flawlessly and will be very useful, thanks again!
– jus cogens prime
Jul 18 '14 at 3:30
add a comment |
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
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
answered Jul 17 '14 at 23:06
GillesGilles
536k12810821600
536k12810821600
Thank you for all the insight!! I think with the first one, I get some interaction because of C1, as if the output lines are context lines of the lines that contained the patterns, whereas they don't themselves contain it - at least I had that with the 3 terms I used for trying out the solutions. Otherwise this works flawlessly and will be very useful, thanks again!
– jus cogens prime
Jul 18 '14 at 3:30
add a comment |
Thank you for all the insight!! I think with the first one, I get some interaction because of C1, as if the output lines are context lines of the lines that contained the patterns, whereas they don't themselves contain it - at least I had that with the 3 terms I used for trying out the solutions. Otherwise this works flawlessly and will be very useful, thanks again!
– jus cogens prime
Jul 18 '14 at 3:30
Thank you for all the insight!! I think with the first one, I get some interaction because of C1, as if the output lines are context lines of the lines that contained the patterns, whereas they don't themselves contain it - at least I had that with the 3 terms I used for trying out the solutions. Otherwise this works flawlessly and will be very useful, thanks again!
– jus cogens prime
Jul 18 '14 at 3:30
Thank you for all the insight!! I think with the first one, I get some interaction because of C1, as if the output lines are context lines of the lines that contained the patterns, whereas they don't themselves contain it - at least I had that with the 3 terms I used for trying out the solutions. Otherwise this works flawlessly and will be very useful, thanks again!
– jus cogens prime
Jul 18 '14 at 3:30
add a comment |
Alternatively, you can use the --file
option to grep:
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file contains
zero patterns, and therefore matches nothing. (-f is specified by POSIX.)
Thanks! The idea is interesting but when you create such a pattern file it's really doing OR i.e. it will find lines with either patterns from that pattern file...
– jus cogens prime
Jul 18 '14 at 9:52
add a comment |
Alternatively, you can use the --file
option to grep:
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file contains
zero patterns, and therefore matches nothing. (-f is specified by POSIX.)
Thanks! The idea is interesting but when you create such a pattern file it's really doing OR i.e. it will find lines with either patterns from that pattern file...
– jus cogens prime
Jul 18 '14 at 9:52
add a comment |
Alternatively, you can use the --file
option to grep:
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file contains
zero patterns, and therefore matches nothing. (-f is specified by POSIX.)
Alternatively, you can use the --file
option to grep:
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file contains
zero patterns, and therefore matches nothing. (-f is specified by POSIX.)
answered Jul 18 '14 at 4:01
Christian MannChristian Mann
1013
1013
Thanks! The idea is interesting but when you create such a pattern file it's really doing OR i.e. it will find lines with either patterns from that pattern file...
– jus cogens prime
Jul 18 '14 at 9:52
add a comment |
Thanks! The idea is interesting but when you create such a pattern file it's really doing OR i.e. it will find lines with either patterns from that pattern file...
– jus cogens prime
Jul 18 '14 at 9:52
Thanks! The idea is interesting but when you create such a pattern file it's really doing OR i.e. it will find lines with either patterns from that pattern file...
– jus cogens prime
Jul 18 '14 at 9:52
Thanks! The idea is interesting but when you create such a pattern file it's really doing OR i.e. it will find lines with either patterns from that pattern file...
– jus cogens prime
Jul 18 '14 at 9:52
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f145196%2fhow-do-you-construct-a-grep-command-to-match-a-number-of-patterns-depending-on%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown