1

How can I extract 3 or more separate text from a line using 'sed'

I have the following line:

echo <MX><[Mike/DOB-029/Post-555/Male]><MX>

So far I am able to extract the 'DOB-029' by doing

sed -n 's/.*\(DOB-[0-9]*\).*/\1/p'

but I am not getting the other texts such as the name or the post.

My expected output should be Mike DOB-029 Post-555

Edited

Say I have a list within a file and I want to extract specific text/IDs from the entire list and save it to a .txt file

4
  • 2
    What's your expected output? Commented Jan 13, 2015 at 13:06
  • my expected output should be Mike DOB-029 Post-555 Commented Jan 13, 2015 at 13:10
  • And what about the last block /Male? What is the logic underlying the problem? Extract everything / separated? Commented Jan 13, 2015 at 13:14
  • I don't want everything. The aim is to show only the first 3 text separated by '/' Commented Jan 13, 2015 at 13:19

3 Answers 3

3

sed 's/.*[\(.*\).\(DOB-[0-9]*\).\(Post-[0-9]*\).*/\1 \2 \3/' should do the trick!

Parts in between \( and \) are captured strings that can be called upon using \i with i the index of the group.

Script for custom use:

#! /bin/bash


fields=${1:-123}
file='/path/to/input'

name=$(sed 's/.*\[\([^\/]*\)\/.*/\1/' $file)
dob=$(sed 's/.*\(DOB-[0-9]*\).*/\1/' $file)
post=$(sed 's/.*\(Post-[0-9]*\).*/\1/' $file)

[[ $fields =~ .*1.* ]] && output=$name
[[ $fields =~ .*2.* ]] && output="$output $dob"
[[ $fields =~ .*3.* ]] && output="$output $post"

echo $output

Set the file with the line you want to parse in the file variable (I can add more functionality such as supplying the file as argument or getting it from a larger file if you like). And execute the script with an int argument, if this int contains '1' it will display name, if 2, it will display DOB and 3 will output post information. You can combine to e.g. '123' or '32' or whichever combination you like.

Stdin

If you want to read from stdin, use following script:

#! /usr/bin/env bash

line=$(cat /dev/stdin)

fields=${1:-123}

name=$(echo $line | sed 's/.*\[\([^\/]*\)\/.*/\1/')
dob=$(echo $line | sed 's/.*\(DOB-[0-9]*\).*/\1/')
post=$(echo $line | sed 's/.*\(Post-[0-9]*\).*/\1/')

[[ $fields =~ .*1.* ]] && output=$name
[[ $fields =~ .*2.* ]] && output="$output $dob"
[[ $fields =~ .*3.* ]] && output="$output $post"

echo $output

Example usage:

$ chmod +x script.sh
$ echo '<MX><[Mike/DOB-029/Post-555/Male]><MX>' | ./script.sh 123
Mike DOB-029 Post-555
$ echo '<MX><[Mike/DOB-029/Post-555/Male]><MX>' | ./script.sh 12
Mike DOB-029
$ echo '<MX><[Mike/DOB-029/Post-555/Male]><MX>' | ./script.sh 32
DOB-029 Post-555
$ echo '<MX><[Mike/DOB-029/Post-555/Male]><MX>' | ./script.sh 
Mike DOB-029 Post-555
Sign up to request clarification or add additional context in comments.

2 Comments

Is there a way to modify this code or create a script so I have the option to take text at different times? So if I want to take the Name only or the DOB-029 or Post-555 or both
My pleasure, you can thank me by accepting the answer :)
3

A solution with awk:

echo "<MX><[Mike/DOB-029/Post-555/Male]><MX>" | awk -F[/[] '{print $2, $3, $4}'

We set the delimiter as / or [ (-F[/[]). then we just print the fields $2, $3 and $4 which are the 2nd, 3rd and 4th fields respectively.

With sed:

echo "<MX><[Mike/DOB-029/Post-555/Male]><MX>" | sed 's/\(^.*\[\)\(.*\)\(\/[^/]*$\)/\2/; s/\// /g'

5 Comments

i fell in love recently.. :-)
If the OP didn't request it for sed, I'd have suggested awk too. A scripting language with the power of a programming language, there's just no way to beat it :)
That is a good idea but it may not work on all the fields I may have, what if the fields are not consistent among multiply files? So the DOB-029 may not be in the 2nd field all the time
@Mikey: Modify your question please, with different scenarios...
@Mikey: or give a scenario where this is not working.. we can fix that up then.
1

use the bash substitution builtins.

line="<MX><[Mike/D0B-029/Post-555/Male]><MX>"; 
linel=${line/*[/}; liner=${linel%\/*}; echo ${liner//\// }

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.