The file you showed has all the details on one line:
name : farah age : 23 phone number : 0123 education : degree
I have assumed that you can hard-code age :
etc into the command, but the text following it will vary, and that the details may not be in the given order or be contiguous.
You can extract parts of the line with grep
's -o
flag. This prints only the matched part, rather than the whole line.
If you want to include the age :
and phone number :
parts, you can either use the -e
flag to specify multiple matches, or alternation.
$ grep -oe 'age : [^ ]*' -e 'phone number : [^ ]*' file
age : 23
phone number : 0123
The expression [^ ]*
means any number of characters that are not a space, so it matches characters after age :
up to the next space.
Replace file
with the name of the file that contains your details. You may write the new file by redirecting the output to a new file with the >
operator, like this:
grep -oe 'age : [^ ]*' -e 'phone number : [^ ]*' file > outfile
When you do that, you won't see any output. You should check the output first, then add redirection.
Here's the example with alternation. We use the -E
flag to tell grep
to use extended regex. The syntax is (pattern1|pattern2)
- this matches pattern1
and/or pattern2
. If either is found, it will be printed (regardless of whether the other is found or not). I'm now using +
meaning at least one of the preceding character, instead of *
meaning zero or more of the preceding character. In this context, they both work equally well.
$ grep -Eo '(age : [^ ]+|phone number : [^ ]+)' file
age : 23
phone number : 0123
If you want to omit the age :
and phone number:
parts, you can use the -P
flag to ask grep
to use Perl-compatible regular expressions. This supports alternation, and also a way of matching text after a given pattern:
$ grep -Po '(age : \K[^ ]+|phone number : \K[^ ]+)' file
23
0123
If you want to format the text differently, you can use sed
, for example:
$ sed -r 's/.*(age) : ([^ ]*).*(phone number) : ([^ ]*).*/\1:\2 | \3:\4/' file
age:23 | phone number:0123
This depends on age
coming before phone number
, so adjust accordingly if that's not the case. If you can't rely on the order, you can use this very convoluted command:
$ sed -r 's/(.*)(phone number : [^ ]+)(.*) .*/\2 \1\4/; s/(phone number) : ([^ ]+) .*(age) : ([^ ]+).*/\1: \2 | \3: \4/' file
phone number: 0123 | age: 23
This rearranges the line so that the phone number :
section comes first on every line, then does a second replacement to select the desired details. I owe the technique used here to this answer by muru.
Notes on sed
commands not covered by previous explanations
-r
use extended regex for more readable commands (GNU sed
understands -E
with the same meaning)
s/old/new/
replace old
with new
(pattern)
saves pattern
to reference later, with \1
or \2
etc (corresponding to the left-to-right order in which the capture groups occur - note that sed
will only hold up to 7 of these!).
.
any character, therefore .*
represents any number of any characters.
;
separates commands, as in the shell.