7

I have a file test.txt, which contains the following result:

service_name1= apple/ball/cat/dog/egg/12.34.56/ball/apple
service_name2= fan/girl/house/ice/joker/23.45.67/fan/girl

and so on up to service_name1500

I want output like :

egg 12.34.56
joker 23.45.67

and so on: the version number along with the word before that.

1
  • is it necessary to do it with grep? I'd use sed or awk
    – SeDav
    Nov 23, 2016 at 10:43

6 Answers 6

11

This should be a simple cut job:

cut -d/ -f5,6 --output-delimiter=" "
  • -d/ sets the input delimiter as /
  • -f5,6 outputs only the 5th and 6th field
  • --output-delimiter=" " sets the output delimiter as a space

Same thing with awk, awk by default sets the output field separator as space:

awk -F/ '{print $5,$6}'

Example:

% cat file.txt
service_name1= apple/ball/cat/dog/egg/12.34.56/ball/apple
service_name2= fan/girl/house/ice/joker/23.45.67/fan/girl

% cut -d/ -f5,6 --output-delimiter=" " file.txt
egg 12.34.56
joker 23.45.67

% awk -F/ '{print $5,$6}' file.txt
egg 12.34.56 
joker 23.45.67
8

a sed solution (works whether the field position of the version string is consistent or not, but the form of the version string must be consistent)

$ sed -r 's#.*/(.*)/([0-9]{2}\.[0-9]{2}\.[0-9]{2}).*#\1 \2#' test.txt
egg 12.34.56

joker 23.45.67

Explanation

  • -r use ERE so we don't have to escape () metacharacters
  • s#old#new# find pattern old and replace with new
  • .* match any or no characters in this position
  • (stuff) remember stuff for later
  • [0-9]{2}\.[0-9]{2}\.[0-9]{2} a pattern of [2 digits].[2 digits].[2 digits]
  • \1 \2 the two remembered patterns with a space in between
5

This will do it:

cut -d'/' -f5-6 test.txt | tr -s "/" " "
3

If you deal with fixed word positions this would work:

grep -e 'service_name[0-9]*=' test.txt|awk -F'/' '{ print $5" "$6 }'
2
$sed -r 's/.*\/([[:alpha:]]+)\/([\.0-9]*)\/.*/\1 \2/' test.txt

Explanation:

  • .* at the beginning and end cuts all characters that do not match the following
  • ([[:alpha:]]+) first subgroup in brackets matches only alphabetical characters
  • \/ matches a slash which will be cut out
  • next subgroup ([\.0-9]*) matches numbers and points and stores it in the second register
  • after the single slash / comes the substitution with \1 \2 inserts the first and second register from the matched subgroups
1

Lengthy but working python one-liner:

$ python -c "import sys;print '\n'.join([ ' '.join(l.strip().split('/')[4:6]) for l in sys.stdin])" < input.txt          
egg 12.34.56
joker 23.45.67

How it works:

  • redirect input file with < into python's stdin stream
  • use list comprehension [item for item in sequence] to read stdin line by line
  • .split() lets us break down lines into list of words using / as separator
  • extract words 4 and 5 ( the [4:6] implies last number is not inclusive ) and make a string out of them using ' '.join()
  • having made list of strings that we want, turn them into lines using '\n'.join() , and print it all out

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.