Can grep output only specified groupings that match?
Clash Royale CLAN TAG#URR8PPP
Say I have a file:
# file: 'test.txt'
foobar bash 1
bash
foobar happy
foobar
I only want to know what words appear after "foobar", so I can use this regex:
"foobar (w+)"
The parenthesis indicate that I have a special interest in the word right after foobar. But when I do a grep "foobar (w+)" test.txt
, I get the entire lines that match the entire regex, rather than just "the word after foobar":
foobar bash 1
foobar happy
I would much prefer that the output of that command looked like this:
bash
happy
Is there a way to tell grep to only output the items that match the grouping (or a specific grouping) in a regular expression?
text-processing grep regular-expression
add a comment |
Say I have a file:
# file: 'test.txt'
foobar bash 1
bash
foobar happy
foobar
I only want to know what words appear after "foobar", so I can use this regex:
"foobar (w+)"
The parenthesis indicate that I have a special interest in the word right after foobar. But when I do a grep "foobar (w+)" test.txt
, I get the entire lines that match the entire regex, rather than just "the word after foobar":
foobar bash 1
foobar happy
I would much prefer that the output of that command looked like this:
bash
happy
Is there a way to tell grep to only output the items that match the grouping (or a specific grouping) in a regular expression?
text-processing grep regular-expression
4
for those who do not need grep:perl -lne 'print $1 if /foobar (w+)/' < test.txt
– vault
Dec 19 '16 at 11:56
add a comment |
Say I have a file:
# file: 'test.txt'
foobar bash 1
bash
foobar happy
foobar
I only want to know what words appear after "foobar", so I can use this regex:
"foobar (w+)"
The parenthesis indicate that I have a special interest in the word right after foobar. But when I do a grep "foobar (w+)" test.txt
, I get the entire lines that match the entire regex, rather than just "the word after foobar":
foobar bash 1
foobar happy
I would much prefer that the output of that command looked like this:
bash
happy
Is there a way to tell grep to only output the items that match the grouping (or a specific grouping) in a regular expression?
text-processing grep regular-expression
Say I have a file:
# file: 'test.txt'
foobar bash 1
bash
foobar happy
foobar
I only want to know what words appear after "foobar", so I can use this regex:
"foobar (w+)"
The parenthesis indicate that I have a special interest in the word right after foobar. But when I do a grep "foobar (w+)" test.txt
, I get the entire lines that match the entire regex, rather than just "the word after foobar":
foobar bash 1
foobar happy
I would much prefer that the output of that command looked like this:
bash
happy
Is there a way to tell grep to only output the items that match the grouping (or a specific grouping) in a regular expression?
text-processing grep regular-expression
text-processing grep regular-expression
edited May 19 '11 at 23:17
Gilles
537k12810881605
537k12810881605
asked May 19 '11 at 23:04
Cory KleinCory Klein
5,452215983
5,452215983
4
for those who do not need grep:perl -lne 'print $1 if /foobar (w+)/' < test.txt
– vault
Dec 19 '16 at 11:56
add a comment |
4
for those who do not need grep:perl -lne 'print $1 if /foobar (w+)/' < test.txt
– vault
Dec 19 '16 at 11:56
4
4
for those who do not need grep:
perl -lne 'print $1 if /foobar (w+)/' < test.txt
– vault
Dec 19 '16 at 11:56
for those who do not need grep:
perl -lne 'print $1 if /foobar (w+)/' < test.txt
– vault
Dec 19 '16 at 11:56
add a comment |
8 Answers
8
active
oldest
votes
GNU grep has the -P
option for perl-style regexes, and the -o
option to print only what matches the pattern. These can be combined using look-around assertions (described under Extended Patterns in the perlre manpage) to remove part of the grep pattern from what is determined to have matched for the purposes of -o
.
$ grep -oP 'foobar Kw+' test.txt
bash
happy
$
The K
is the short-form (and more efficient form) of (?<=pattern)
which you use as a zero-width look-behind assertion before the text you want to output. (?=pattern)
can be used as a zero-width look-ahead assertion after the text you want to output.
For instance, if you wanted to match the word between foo
and bar
, you could use:
$ grep -oP 'foo Kw+(?= bar)' test.txt
or (for symmetry)
$ grep -oP '(?<=foo )w+(?= bar)' test.txt
2
How you do it if your regex has more than a grouping? (as the title implied?)
– barracel
Mar 21 '13 at 7:52
3
@barracel: I don't believe you can. Time forsed(1)
– camh
Mar 22 '13 at 22:51
1
@camh I have just tested thatgrep -oP 'foobar Kw+' test.txt
outputs nothing with the OP'stest.txt
. The grep version is 2.5.1. What could be wrong ? O_O
– SOUser
Jul 24 '14 at 14:19
@XichenLi: I can't say. I just built v2.5.1 of grep (it's pretty old - from 2006) and it worked for me.
– camh
Jul 25 '14 at 10:18
@SOUser: I experienced the same - outputs nothing to file. I submitted the edit request to include '>' before the filename to send output as this worked for me.
– rjchicago
Dec 15 '16 at 21:40
|
show 3 more comments
Standard grep can't do this, but recent versions of GNU grep can. You can turn to sed, awk or perl. Here are a few examples that do what you want on your sample input; they behave slightly differently in corner cases.
Replace foobar word other stuff
by word
, print only if a replacement is done.
sed -n -e 's/^foobar ([[:alnum:]]+).*/1/p'
If the first word is foobar
, print the second word.
awk '$1 == "foobar" print $2'
Strip foobar
if it's the first word, and skip the line otherwise; then strip everything after the first whitespace and print.
perl -lne 's/^foobars+// or next; s/s.*//; print'
Awesome! I thought I may be able to do this with sed, but I haven't used it before and was hoping I could use my familiargrep
. But the syntax for these commands actually looks very familiar now that I am familiar with vim-style search & replace + regexes. Thanks a ton.
– Cory Klein
May 19 '11 at 23:51
1
Not true, Gilles. See my answer for a GNU grep solution.
– camh
May 20 '11 at 1:33
1
@camh: Ah, I didn't know GNU grep now had full PCRE support. I've corrected my answer, thanks.
– Gilles
May 20 '11 at 7:14
This answer is especially useful for embedded Linux since Busyboxgrep
doesn't have PCRE support.
– Craig McQueen
Mar 17 '16 at 0:12
add a comment |
sed -n "s/^.*foobars*(S*).*$/1/p"
-n suppress printing
s substitute
^.* anything before foobar
foobar initial search match
s* any white space character (space)
( start capture group
S* capture any non-white space character (word)
) end capture group
.*$ anything after the capture group
1 substitute everything with the 1st capture group
p print it
1
+1 for the sed example, seems like a better tool for the job than grep. One comment, the^
and$
are extraneous since.*
is a greedy match. However, including them might help clarify the intent of the regex.
– Tony
May 30 '18 at 21:22
add a comment |
Well, if you know that foobar is always the first word or the line, then you can use cut. Like so:
grep "foobar" test.file | cut -d" " -f2
The-o
switch on grep is widely implemented (moreso than the Gnu grep extensions), so doinggrep -o "foobar" test.file | cut -d" " -f2
will increase the effectiveness of this solution, which is more portable than using lookbehind assertions.
– dubiousjim
Apr 19 '12 at 21:04
I believe that you would needgrep -o "foobar .*
" orgrep -o "foobar w+"
.
– G-Man
Apr 14 '18 at 7:20
add a comment |
If PCRE is not supported you can achieve the same result with two invocations of grep. For example to grab the word after foobar do this:
<test.txt grep -o 'foobar *[^ ]*' | grep -o '[^ ]*$'
This can be expanded to an arbitrary word after foobar like this (with EREs for readability):
i=1
<test.txt egrep -o 'foobar +([^ ]+ +)'$i'[^ ]+' | grep -o '[^ ]*$'
Output:
1
Note the index i
is zero-based.
add a comment |
pcregrep
has a smarter -o
option
that lets you choose which capturing groups you want output.
So, using your example file,
$ pcregrep -o1 "foobar (w+)" test.txt
bash
happy
add a comment |
Using grep
is not cross-platform compatible, since -P
/--perl-regexp
is only available on GNU grep
, not BSD grep
.
Here is the solution using ripgrep
:
$ rg -o "foobar (w+)" -r '$1' <test.txt
bash
happy
As per man rg
:
-r
/--replace REPLACEMENT_TEXT
Replace every match with the text given.
Capture group indices (e.g.,
$5
) and names (e.g.,$foo
) are supported in the replacement string.
Related: GH-462.
add a comment |
I found the answer of @jgshawkey very helpful. grep
is not such a good tool for this, but sed is, although here we have an example that uses grep to grab a relevant line.
Regex syntax of sed is idiosyncratic if you are not used to it.
Here is another example: this one parses output of xinput to get an ID integer
⎜ ↳ SynPS/2 Synaptics TouchPad id=19 [slave pointer (2)]
and I want 19
export TouchPadID=$(xinput | grep 'TouchPad' | sed -n "s/^.*id=([[:digit:]]+).*$/1/p")
Note the class syntax:
[[:digit:]]
and the need to escape the following +
I assume only one line matches.
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%2f13466%2fcan-grep-output-only-specified-groupings-that-match%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
8 Answers
8
active
oldest
votes
8 Answers
8
active
oldest
votes
active
oldest
votes
active
oldest
votes
GNU grep has the -P
option for perl-style regexes, and the -o
option to print only what matches the pattern. These can be combined using look-around assertions (described under Extended Patterns in the perlre manpage) to remove part of the grep pattern from what is determined to have matched for the purposes of -o
.
$ grep -oP 'foobar Kw+' test.txt
bash
happy
$
The K
is the short-form (and more efficient form) of (?<=pattern)
which you use as a zero-width look-behind assertion before the text you want to output. (?=pattern)
can be used as a zero-width look-ahead assertion after the text you want to output.
For instance, if you wanted to match the word between foo
and bar
, you could use:
$ grep -oP 'foo Kw+(?= bar)' test.txt
or (for symmetry)
$ grep -oP '(?<=foo )w+(?= bar)' test.txt
2
How you do it if your regex has more than a grouping? (as the title implied?)
– barracel
Mar 21 '13 at 7:52
3
@barracel: I don't believe you can. Time forsed(1)
– camh
Mar 22 '13 at 22:51
1
@camh I have just tested thatgrep -oP 'foobar Kw+' test.txt
outputs nothing with the OP'stest.txt
. The grep version is 2.5.1. What could be wrong ? O_O
– SOUser
Jul 24 '14 at 14:19
@XichenLi: I can't say. I just built v2.5.1 of grep (it's pretty old - from 2006) and it worked for me.
– camh
Jul 25 '14 at 10:18
@SOUser: I experienced the same - outputs nothing to file. I submitted the edit request to include '>' before the filename to send output as this worked for me.
– rjchicago
Dec 15 '16 at 21:40
|
show 3 more comments
GNU grep has the -P
option for perl-style regexes, and the -o
option to print only what matches the pattern. These can be combined using look-around assertions (described under Extended Patterns in the perlre manpage) to remove part of the grep pattern from what is determined to have matched for the purposes of -o
.
$ grep -oP 'foobar Kw+' test.txt
bash
happy
$
The K
is the short-form (and more efficient form) of (?<=pattern)
which you use as a zero-width look-behind assertion before the text you want to output. (?=pattern)
can be used as a zero-width look-ahead assertion after the text you want to output.
For instance, if you wanted to match the word between foo
and bar
, you could use:
$ grep -oP 'foo Kw+(?= bar)' test.txt
or (for symmetry)
$ grep -oP '(?<=foo )w+(?= bar)' test.txt
2
How you do it if your regex has more than a grouping? (as the title implied?)
– barracel
Mar 21 '13 at 7:52
3
@barracel: I don't believe you can. Time forsed(1)
– camh
Mar 22 '13 at 22:51
1
@camh I have just tested thatgrep -oP 'foobar Kw+' test.txt
outputs nothing with the OP'stest.txt
. The grep version is 2.5.1. What could be wrong ? O_O
– SOUser
Jul 24 '14 at 14:19
@XichenLi: I can't say. I just built v2.5.1 of grep (it's pretty old - from 2006) and it worked for me.
– camh
Jul 25 '14 at 10:18
@SOUser: I experienced the same - outputs nothing to file. I submitted the edit request to include '>' before the filename to send output as this worked for me.
– rjchicago
Dec 15 '16 at 21:40
|
show 3 more comments
GNU grep has the -P
option for perl-style regexes, and the -o
option to print only what matches the pattern. These can be combined using look-around assertions (described under Extended Patterns in the perlre manpage) to remove part of the grep pattern from what is determined to have matched for the purposes of -o
.
$ grep -oP 'foobar Kw+' test.txt
bash
happy
$
The K
is the short-form (and more efficient form) of (?<=pattern)
which you use as a zero-width look-behind assertion before the text you want to output. (?=pattern)
can be used as a zero-width look-ahead assertion after the text you want to output.
For instance, if you wanted to match the word between foo
and bar
, you could use:
$ grep -oP 'foo Kw+(?= bar)' test.txt
or (for symmetry)
$ grep -oP '(?<=foo )w+(?= bar)' test.txt
GNU grep has the -P
option for perl-style regexes, and the -o
option to print only what matches the pattern. These can be combined using look-around assertions (described under Extended Patterns in the perlre manpage) to remove part of the grep pattern from what is determined to have matched for the purposes of -o
.
$ grep -oP 'foobar Kw+' test.txt
bash
happy
$
The K
is the short-form (and more efficient form) of (?<=pattern)
which you use as a zero-width look-behind assertion before the text you want to output. (?=pattern)
can be used as a zero-width look-ahead assertion after the text you want to output.
For instance, if you wanted to match the word between foo
and bar
, you could use:
$ grep -oP 'foo Kw+(?= bar)' test.txt
or (for symmetry)
$ grep -oP '(?<=foo )w+(?= bar)' test.txt
edited May 20 '11 at 1:50
answered May 20 '11 at 1:33
camhcamh
24.9k76352
24.9k76352
2
How you do it if your regex has more than a grouping? (as the title implied?)
– barracel
Mar 21 '13 at 7:52
3
@barracel: I don't believe you can. Time forsed(1)
– camh
Mar 22 '13 at 22:51
1
@camh I have just tested thatgrep -oP 'foobar Kw+' test.txt
outputs nothing with the OP'stest.txt
. The grep version is 2.5.1. What could be wrong ? O_O
– SOUser
Jul 24 '14 at 14:19
@XichenLi: I can't say. I just built v2.5.1 of grep (it's pretty old - from 2006) and it worked for me.
– camh
Jul 25 '14 at 10:18
@SOUser: I experienced the same - outputs nothing to file. I submitted the edit request to include '>' before the filename to send output as this worked for me.
– rjchicago
Dec 15 '16 at 21:40
|
show 3 more comments
2
How you do it if your regex has more than a grouping? (as the title implied?)
– barracel
Mar 21 '13 at 7:52
3
@barracel: I don't believe you can. Time forsed(1)
– camh
Mar 22 '13 at 22:51
1
@camh I have just tested thatgrep -oP 'foobar Kw+' test.txt
outputs nothing with the OP'stest.txt
. The grep version is 2.5.1. What could be wrong ? O_O
– SOUser
Jul 24 '14 at 14:19
@XichenLi: I can't say. I just built v2.5.1 of grep (it's pretty old - from 2006) and it worked for me.
– camh
Jul 25 '14 at 10:18
@SOUser: I experienced the same - outputs nothing to file. I submitted the edit request to include '>' before the filename to send output as this worked for me.
– rjchicago
Dec 15 '16 at 21:40
2
2
How you do it if your regex has more than a grouping? (as the title implied?)
– barracel
Mar 21 '13 at 7:52
How you do it if your regex has more than a grouping? (as the title implied?)
– barracel
Mar 21 '13 at 7:52
3
3
@barracel: I don't believe you can. Time for
sed(1)
– camh
Mar 22 '13 at 22:51
@barracel: I don't believe you can. Time for
sed(1)
– camh
Mar 22 '13 at 22:51
1
1
@camh I have just tested that
grep -oP 'foobar Kw+' test.txt
outputs nothing with the OP's test.txt
. The grep version is 2.5.1. What could be wrong ? O_O– SOUser
Jul 24 '14 at 14:19
@camh I have just tested that
grep -oP 'foobar Kw+' test.txt
outputs nothing with the OP's test.txt
. The grep version is 2.5.1. What could be wrong ? O_O– SOUser
Jul 24 '14 at 14:19
@XichenLi: I can't say. I just built v2.5.1 of grep (it's pretty old - from 2006) and it worked for me.
– camh
Jul 25 '14 at 10:18
@XichenLi: I can't say. I just built v2.5.1 of grep (it's pretty old - from 2006) and it worked for me.
– camh
Jul 25 '14 at 10:18
@SOUser: I experienced the same - outputs nothing to file. I submitted the edit request to include '>' before the filename to send output as this worked for me.
– rjchicago
Dec 15 '16 at 21:40
@SOUser: I experienced the same - outputs nothing to file. I submitted the edit request to include '>' before the filename to send output as this worked for me.
– rjchicago
Dec 15 '16 at 21:40
|
show 3 more comments
Standard grep can't do this, but recent versions of GNU grep can. You can turn to sed, awk or perl. Here are a few examples that do what you want on your sample input; they behave slightly differently in corner cases.
Replace foobar word other stuff
by word
, print only if a replacement is done.
sed -n -e 's/^foobar ([[:alnum:]]+).*/1/p'
If the first word is foobar
, print the second word.
awk '$1 == "foobar" print $2'
Strip foobar
if it's the first word, and skip the line otherwise; then strip everything after the first whitespace and print.
perl -lne 's/^foobars+// or next; s/s.*//; print'
Awesome! I thought I may be able to do this with sed, but I haven't used it before and was hoping I could use my familiargrep
. But the syntax for these commands actually looks very familiar now that I am familiar with vim-style search & replace + regexes. Thanks a ton.
– Cory Klein
May 19 '11 at 23:51
1
Not true, Gilles. See my answer for a GNU grep solution.
– camh
May 20 '11 at 1:33
1
@camh: Ah, I didn't know GNU grep now had full PCRE support. I've corrected my answer, thanks.
– Gilles
May 20 '11 at 7:14
This answer is especially useful for embedded Linux since Busyboxgrep
doesn't have PCRE support.
– Craig McQueen
Mar 17 '16 at 0:12
add a comment |
Standard grep can't do this, but recent versions of GNU grep can. You can turn to sed, awk or perl. Here are a few examples that do what you want on your sample input; they behave slightly differently in corner cases.
Replace foobar word other stuff
by word
, print only if a replacement is done.
sed -n -e 's/^foobar ([[:alnum:]]+).*/1/p'
If the first word is foobar
, print the second word.
awk '$1 == "foobar" print $2'
Strip foobar
if it's the first word, and skip the line otherwise; then strip everything after the first whitespace and print.
perl -lne 's/^foobars+// or next; s/s.*//; print'
Awesome! I thought I may be able to do this with sed, but I haven't used it before and was hoping I could use my familiargrep
. But the syntax for these commands actually looks very familiar now that I am familiar with vim-style search & replace + regexes. Thanks a ton.
– Cory Klein
May 19 '11 at 23:51
1
Not true, Gilles. See my answer for a GNU grep solution.
– camh
May 20 '11 at 1:33
1
@camh: Ah, I didn't know GNU grep now had full PCRE support. I've corrected my answer, thanks.
– Gilles
May 20 '11 at 7:14
This answer is especially useful for embedded Linux since Busyboxgrep
doesn't have PCRE support.
– Craig McQueen
Mar 17 '16 at 0:12
add a comment |
Standard grep can't do this, but recent versions of GNU grep can. You can turn to sed, awk or perl. Here are a few examples that do what you want on your sample input; they behave slightly differently in corner cases.
Replace foobar word other stuff
by word
, print only if a replacement is done.
sed -n -e 's/^foobar ([[:alnum:]]+).*/1/p'
If the first word is foobar
, print the second word.
awk '$1 == "foobar" print $2'
Strip foobar
if it's the first word, and skip the line otherwise; then strip everything after the first whitespace and print.
perl -lne 's/^foobars+// or next; s/s.*//; print'
Standard grep can't do this, but recent versions of GNU grep can. You can turn to sed, awk or perl. Here are a few examples that do what you want on your sample input; they behave slightly differently in corner cases.
Replace foobar word other stuff
by word
, print only if a replacement is done.
sed -n -e 's/^foobar ([[:alnum:]]+).*/1/p'
If the first word is foobar
, print the second word.
awk '$1 == "foobar" print $2'
Strip foobar
if it's the first word, and skip the line otherwise; then strip everything after the first whitespace and print.
perl -lne 's/^foobars+// or next; s/s.*//; print'
edited Apr 13 '17 at 12:36
Community♦
1
1
answered May 19 '11 at 23:17
GillesGilles
537k12810881605
537k12810881605
Awesome! I thought I may be able to do this with sed, but I haven't used it before and was hoping I could use my familiargrep
. But the syntax for these commands actually looks very familiar now that I am familiar with vim-style search & replace + regexes. Thanks a ton.
– Cory Klein
May 19 '11 at 23:51
1
Not true, Gilles. See my answer for a GNU grep solution.
– camh
May 20 '11 at 1:33
1
@camh: Ah, I didn't know GNU grep now had full PCRE support. I've corrected my answer, thanks.
– Gilles
May 20 '11 at 7:14
This answer is especially useful for embedded Linux since Busyboxgrep
doesn't have PCRE support.
– Craig McQueen
Mar 17 '16 at 0:12
add a comment |
Awesome! I thought I may be able to do this with sed, but I haven't used it before and was hoping I could use my familiargrep
. But the syntax for these commands actually looks very familiar now that I am familiar with vim-style search & replace + regexes. Thanks a ton.
– Cory Klein
May 19 '11 at 23:51
1
Not true, Gilles. See my answer for a GNU grep solution.
– camh
May 20 '11 at 1:33
1
@camh: Ah, I didn't know GNU grep now had full PCRE support. I've corrected my answer, thanks.
– Gilles
May 20 '11 at 7:14
This answer is especially useful for embedded Linux since Busyboxgrep
doesn't have PCRE support.
– Craig McQueen
Mar 17 '16 at 0:12
Awesome! I thought I may be able to do this with sed, but I haven't used it before and was hoping I could use my familiar
grep
. But the syntax for these commands actually looks very familiar now that I am familiar with vim-style search & replace + regexes. Thanks a ton.– Cory Klein
May 19 '11 at 23:51
Awesome! I thought I may be able to do this with sed, but I haven't used it before and was hoping I could use my familiar
grep
. But the syntax for these commands actually looks very familiar now that I am familiar with vim-style search & replace + regexes. Thanks a ton.– Cory Klein
May 19 '11 at 23:51
1
1
Not true, Gilles. See my answer for a GNU grep solution.
– camh
May 20 '11 at 1:33
Not true, Gilles. See my answer for a GNU grep solution.
– camh
May 20 '11 at 1:33
1
1
@camh: Ah, I didn't know GNU grep now had full PCRE support. I've corrected my answer, thanks.
– Gilles
May 20 '11 at 7:14
@camh: Ah, I didn't know GNU grep now had full PCRE support. I've corrected my answer, thanks.
– Gilles
May 20 '11 at 7:14
This answer is especially useful for embedded Linux since Busybox
grep
doesn't have PCRE support.– Craig McQueen
Mar 17 '16 at 0:12
This answer is especially useful for embedded Linux since Busybox
grep
doesn't have PCRE support.– Craig McQueen
Mar 17 '16 at 0:12
add a comment |
sed -n "s/^.*foobars*(S*).*$/1/p"
-n suppress printing
s substitute
^.* anything before foobar
foobar initial search match
s* any white space character (space)
( start capture group
S* capture any non-white space character (word)
) end capture group
.*$ anything after the capture group
1 substitute everything with the 1st capture group
p print it
1
+1 for the sed example, seems like a better tool for the job than grep. One comment, the^
and$
are extraneous since.*
is a greedy match. However, including them might help clarify the intent of the regex.
– Tony
May 30 '18 at 21:22
add a comment |
sed -n "s/^.*foobars*(S*).*$/1/p"
-n suppress printing
s substitute
^.* anything before foobar
foobar initial search match
s* any white space character (space)
( start capture group
S* capture any non-white space character (word)
) end capture group
.*$ anything after the capture group
1 substitute everything with the 1st capture group
p print it
1
+1 for the sed example, seems like a better tool for the job than grep. One comment, the^
and$
are extraneous since.*
is a greedy match. However, including them might help clarify the intent of the regex.
– Tony
May 30 '18 at 21:22
add a comment |
sed -n "s/^.*foobars*(S*).*$/1/p"
-n suppress printing
s substitute
^.* anything before foobar
foobar initial search match
s* any white space character (space)
( start capture group
S* capture any non-white space character (word)
) end capture group
.*$ anything after the capture group
1 substitute everything with the 1st capture group
p print it
sed -n "s/^.*foobars*(S*).*$/1/p"
-n suppress printing
s substitute
^.* anything before foobar
foobar initial search match
s* any white space character (space)
( start capture group
S* capture any non-white space character (word)
) end capture group
.*$ anything after the capture group
1 substitute everything with the 1st capture group
p print it
answered Apr 22 '16 at 16:08
jgshawkeyjgshawkey
30122
30122
1
+1 for the sed example, seems like a better tool for the job than grep. One comment, the^
and$
are extraneous since.*
is a greedy match. However, including them might help clarify the intent of the regex.
– Tony
May 30 '18 at 21:22
add a comment |
1
+1 for the sed example, seems like a better tool for the job than grep. One comment, the^
and$
are extraneous since.*
is a greedy match. However, including them might help clarify the intent of the regex.
– Tony
May 30 '18 at 21:22
1
1
+1 for the sed example, seems like a better tool for the job than grep. One comment, the
^
and $
are extraneous since .*
is a greedy match. However, including them might help clarify the intent of the regex.– Tony
May 30 '18 at 21:22
+1 for the sed example, seems like a better tool for the job than grep. One comment, the
^
and $
are extraneous since .*
is a greedy match. However, including them might help clarify the intent of the regex.– Tony
May 30 '18 at 21:22
add a comment |
Well, if you know that foobar is always the first word or the line, then you can use cut. Like so:
grep "foobar" test.file | cut -d" " -f2
The-o
switch on grep is widely implemented (moreso than the Gnu grep extensions), so doinggrep -o "foobar" test.file | cut -d" " -f2
will increase the effectiveness of this solution, which is more portable than using lookbehind assertions.
– dubiousjim
Apr 19 '12 at 21:04
I believe that you would needgrep -o "foobar .*
" orgrep -o "foobar w+"
.
– G-Man
Apr 14 '18 at 7:20
add a comment |
Well, if you know that foobar is always the first word or the line, then you can use cut. Like so:
grep "foobar" test.file | cut -d" " -f2
The-o
switch on grep is widely implemented (moreso than the Gnu grep extensions), so doinggrep -o "foobar" test.file | cut -d" " -f2
will increase the effectiveness of this solution, which is more portable than using lookbehind assertions.
– dubiousjim
Apr 19 '12 at 21:04
I believe that you would needgrep -o "foobar .*
" orgrep -o "foobar w+"
.
– G-Man
Apr 14 '18 at 7:20
add a comment |
Well, if you know that foobar is always the first word or the line, then you can use cut. Like so:
grep "foobar" test.file | cut -d" " -f2
Well, if you know that foobar is always the first word or the line, then you can use cut. Like so:
grep "foobar" test.file | cut -d" " -f2
answered May 20 '11 at 1:07
DaveDave
25112
25112
The-o
switch on grep is widely implemented (moreso than the Gnu grep extensions), so doinggrep -o "foobar" test.file | cut -d" " -f2
will increase the effectiveness of this solution, which is more portable than using lookbehind assertions.
– dubiousjim
Apr 19 '12 at 21:04
I believe that you would needgrep -o "foobar .*
" orgrep -o "foobar w+"
.
– G-Man
Apr 14 '18 at 7:20
add a comment |
The-o
switch on grep is widely implemented (moreso than the Gnu grep extensions), so doinggrep -o "foobar" test.file | cut -d" " -f2
will increase the effectiveness of this solution, which is more portable than using lookbehind assertions.
– dubiousjim
Apr 19 '12 at 21:04
I believe that you would needgrep -o "foobar .*
" orgrep -o "foobar w+"
.
– G-Man
Apr 14 '18 at 7:20
The
-o
switch on grep is widely implemented (moreso than the Gnu grep extensions), so doing grep -o "foobar" test.file | cut -d" " -f2
will increase the effectiveness of this solution, which is more portable than using lookbehind assertions.– dubiousjim
Apr 19 '12 at 21:04
The
-o
switch on grep is widely implemented (moreso than the Gnu grep extensions), so doing grep -o "foobar" test.file | cut -d" " -f2
will increase the effectiveness of this solution, which is more portable than using lookbehind assertions.– dubiousjim
Apr 19 '12 at 21:04
I believe that you would need
grep -o "foobar .*
" or grep -o "foobar w+"
.– G-Man
Apr 14 '18 at 7:20
I believe that you would need
grep -o "foobar .*
" or grep -o "foobar w+"
.– G-Man
Apr 14 '18 at 7:20
add a comment |
If PCRE is not supported you can achieve the same result with two invocations of grep. For example to grab the word after foobar do this:
<test.txt grep -o 'foobar *[^ ]*' | grep -o '[^ ]*$'
This can be expanded to an arbitrary word after foobar like this (with EREs for readability):
i=1
<test.txt egrep -o 'foobar +([^ ]+ +)'$i'[^ ]+' | grep -o '[^ ]*$'
Output:
1
Note the index i
is zero-based.
add a comment |
If PCRE is not supported you can achieve the same result with two invocations of grep. For example to grab the word after foobar do this:
<test.txt grep -o 'foobar *[^ ]*' | grep -o '[^ ]*$'
This can be expanded to an arbitrary word after foobar like this (with EREs for readability):
i=1
<test.txt egrep -o 'foobar +([^ ]+ +)'$i'[^ ]+' | grep -o '[^ ]*$'
Output:
1
Note the index i
is zero-based.
add a comment |
If PCRE is not supported you can achieve the same result with two invocations of grep. For example to grab the word after foobar do this:
<test.txt grep -o 'foobar *[^ ]*' | grep -o '[^ ]*$'
This can be expanded to an arbitrary word after foobar like this (with EREs for readability):
i=1
<test.txt egrep -o 'foobar +([^ ]+ +)'$i'[^ ]+' | grep -o '[^ ]*$'
Output:
1
Note the index i
is zero-based.
If PCRE is not supported you can achieve the same result with two invocations of grep. For example to grab the word after foobar do this:
<test.txt grep -o 'foobar *[^ ]*' | grep -o '[^ ]*$'
This can be expanded to an arbitrary word after foobar like this (with EREs for readability):
i=1
<test.txt egrep -o 'foobar +([^ ]+ +)'$i'[^ ]+' | grep -o '[^ ]*$'
Output:
1
Note the index i
is zero-based.
answered Oct 8 '13 at 12:38
ThorThor
11.8k13459
11.8k13459
add a comment |
add a comment |
pcregrep
has a smarter -o
option
that lets you choose which capturing groups you want output.
So, using your example file,
$ pcregrep -o1 "foobar (w+)" test.txt
bash
happy
add a comment |
pcregrep
has a smarter -o
option
that lets you choose which capturing groups you want output.
So, using your example file,
$ pcregrep -o1 "foobar (w+)" test.txt
bash
happy
add a comment |
pcregrep
has a smarter -o
option
that lets you choose which capturing groups you want output.
So, using your example file,
$ pcregrep -o1 "foobar (w+)" test.txt
bash
happy
pcregrep
has a smarter -o
option
that lets you choose which capturing groups you want output.
So, using your example file,
$ pcregrep -o1 "foobar (w+)" test.txt
bash
happy
answered Apr 14 '18 at 7:29
G-ManG-Man
13.1k93465
13.1k93465
add a comment |
add a comment |
Using grep
is not cross-platform compatible, since -P
/--perl-regexp
is only available on GNU grep
, not BSD grep
.
Here is the solution using ripgrep
:
$ rg -o "foobar (w+)" -r '$1' <test.txt
bash
happy
As per man rg
:
-r
/--replace REPLACEMENT_TEXT
Replace every match with the text given.
Capture group indices (e.g.,
$5
) and names (e.g.,$foo
) are supported in the replacement string.
Related: GH-462.
add a comment |
Using grep
is not cross-platform compatible, since -P
/--perl-regexp
is only available on GNU grep
, not BSD grep
.
Here is the solution using ripgrep
:
$ rg -o "foobar (w+)" -r '$1' <test.txt
bash
happy
As per man rg
:
-r
/--replace REPLACEMENT_TEXT
Replace every match with the text given.
Capture group indices (e.g.,
$5
) and names (e.g.,$foo
) are supported in the replacement string.
Related: GH-462.
add a comment |
Using grep
is not cross-platform compatible, since -P
/--perl-regexp
is only available on GNU grep
, not BSD grep
.
Here is the solution using ripgrep
:
$ rg -o "foobar (w+)" -r '$1' <test.txt
bash
happy
As per man rg
:
-r
/--replace REPLACEMENT_TEXT
Replace every match with the text given.
Capture group indices (e.g.,
$5
) and names (e.g.,$foo
) are supported in the replacement string.
Related: GH-462.
Using grep
is not cross-platform compatible, since -P
/--perl-regexp
is only available on GNU grep
, not BSD grep
.
Here is the solution using ripgrep
:
$ rg -o "foobar (w+)" -r '$1' <test.txt
bash
happy
As per man rg
:
-r
/--replace REPLACEMENT_TEXT
Replace every match with the text given.
Capture group indices (e.g.,
$5
) and names (e.g.,$foo
) are supported in the replacement string.
Related: GH-462.
answered Apr 16 '18 at 15:35
kenorbkenorb
8,736372108
8,736372108
add a comment |
add a comment |
I found the answer of @jgshawkey very helpful. grep
is not such a good tool for this, but sed is, although here we have an example that uses grep to grab a relevant line.
Regex syntax of sed is idiosyncratic if you are not used to it.
Here is another example: this one parses output of xinput to get an ID integer
⎜ ↳ SynPS/2 Synaptics TouchPad id=19 [slave pointer (2)]
and I want 19
export TouchPadID=$(xinput | grep 'TouchPad' | sed -n "s/^.*id=([[:digit:]]+).*$/1/p")
Note the class syntax:
[[:digit:]]
and the need to escape the following +
I assume only one line matches.
add a comment |
I found the answer of @jgshawkey very helpful. grep
is not such a good tool for this, but sed is, although here we have an example that uses grep to grab a relevant line.
Regex syntax of sed is idiosyncratic if you are not used to it.
Here is another example: this one parses output of xinput to get an ID integer
⎜ ↳ SynPS/2 Synaptics TouchPad id=19 [slave pointer (2)]
and I want 19
export TouchPadID=$(xinput | grep 'TouchPad' | sed -n "s/^.*id=([[:digit:]]+).*$/1/p")
Note the class syntax:
[[:digit:]]
and the need to escape the following +
I assume only one line matches.
add a comment |
I found the answer of @jgshawkey very helpful. grep
is not such a good tool for this, but sed is, although here we have an example that uses grep to grab a relevant line.
Regex syntax of sed is idiosyncratic if you are not used to it.
Here is another example: this one parses output of xinput to get an ID integer
⎜ ↳ SynPS/2 Synaptics TouchPad id=19 [slave pointer (2)]
and I want 19
export TouchPadID=$(xinput | grep 'TouchPad' | sed -n "s/^.*id=([[:digit:]]+).*$/1/p")
Note the class syntax:
[[:digit:]]
and the need to escape the following +
I assume only one line matches.
I found the answer of @jgshawkey very helpful. grep
is not such a good tool for this, but sed is, although here we have an example that uses grep to grab a relevant line.
Regex syntax of sed is idiosyncratic if you are not used to it.
Here is another example: this one parses output of xinput to get an ID integer
⎜ ↳ SynPS/2 Synaptics TouchPad id=19 [slave pointer (2)]
and I want 19
export TouchPadID=$(xinput | grep 'TouchPad' | sed -n "s/^.*id=([[:digit:]]+).*$/1/p")
Note the class syntax:
[[:digit:]]
and the need to escape the following +
I assume only one line matches.
answered Jan 29 at 8:29
Tim RichardsonTim Richardson
1012
1012
add a comment |
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%2f13466%2fcan-grep-output-only-specified-groupings-that-match%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
4
for those who do not need grep:
perl -lne 'print $1 if /foobar (w+)/' < test.txt
– vault
Dec 19 '16 at 11:56