Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm working on bash script.

I have a var with a string in it. This is the string:

tSA_15_20161014_11-12-50

Basically the format is tSA_(id)_(year)(month)(day)_(hour)-(min)-(seg)

Important information:

  • The id can be a number from 0 to 999
  • The year format is yyyy
  • Month format mm
  • Day format dd
  • Hour format 24h

The string I want to get is something like:

20161014111250

Which is yyyymmddHHMMSS

English is not my native language, so if there's something you can't understand please tell me. Thank you.

share|improve this question
up vote 8 down vote accepted
echo "tSA_15_20161014_11-12-50" | awk -F'_' '{print $3$4}' | tr -d -

echo the var in which the string is stored

Explanation:

awk -F'_' '{print $3$4}' change the field separator to _ and print the 3rd and 4th column

The output is 2016101411-12-50

tr -d - deletes - from the previous result.

share|improve this answer
    
Exactly what I was looking for. Thanks a lot @debal – gloaiza 2 days ago
1  
Or simply: echo "tSA_15_20161014_11-12-50" | awk -F'_' '{gsub("-", "", $4); print $3$4}' – heemayl 2 days ago
    
if this works out, could you please accept it as an answer and upvote it. :) – debal 2 days ago

With bash parameter expansion:

$ var='tSA_15_20161014_11-12-50'

$ var="${var#*_}"  ## Extracts the portion after first `_` i.e. 
                      new `var` will be `15_20161014_11-12-50`

$ var="${var#*_}"  ## again gets the portion after first `_`, so in this case
                      after operation `var` will contain `20161014_11-12-50`

$ echo "${var//[-_]/}"  ## Replaces all `-` and `_` from `$var` with null
20161014111250
share|improve this answer
1  
I like this answer more as you provided a pure bash solution as specified by the OP. – Aditya K yesterday
1  
+1, but every one of those quotes except the very last pair is unnecessary and does nothing. Substitutions inside assignments (second and third line) are not subject to word splitting. And the first like doesn't have any whitespace in it. – mtraceur yesterday
    
@mtraceur I know, that's just the muscle memory :) – heemayl yesterday

Given

var='tSA_15_20161014_11-12-50'

then

IFS=_ read -a arr <<< "${var//-/}"
printf '%s%s\n' "${arr[2]}" "${arr[3]}"
20161014111250
share|improve this answer

For completeness, a few sed versions:

echo "tSA_15_20161014_11-12-50" \
| sed -rn 's/^tSA_[0-9]{1,3}_([0-9]{8})_([0-9]{2})-([0-9]{2})-([0-9]{2})$/\1\2\3\4/p'

echo "tSA_15_20161014_11-12-50" \
| sed -r 's/^tSA_[0-9]{1,3}_([0-9]{8})_([0-9]{2})-([0-9]{2})-([0-9]{2})$/\1\2\3\4/'

echo "tSA_15_20161014_11-12-50" \
| sed -r 's/([^_]*_){2}(.*)_(.*)/\2\3/;s/-//g'

echo "tSA_15_20161014_11-12-50" \
| sed -r 's/(.*_){3}/\1/;s/[-_]//g'

One thing I find important is error checking. In case the variable does not conform exactly to the format you have given, the first version will yield an empty string, and the second version will yield the input string, unchanged. The third version is a sed version of @debal's awk answer, and the fourth is as concise as I can easily get it, both without specified behavior on incorrect input.

share|improve this answer

Another awk approach. Since awk can take multiple characters as field separators, this can be done in a single step:

$ awk -F'[-_]' '{print $3$4$5$6}' <<<"$var"
20161014111250

Alternatively, in Perl:

$ perl -pe 's/.+?_.+?_//; s/[-_]//g' <<<"$var"
20161014111250

Or

$ perl -F_ -ane 's/-//g for @F; print @F[2..$#F]' <<<"$var"
20161014111250

I'm using here strings, but if your shell doesn't support them just echo $var | command for each command above.

share|improve this answer

Python solution, using re.split() with multiple tokens. Input string is provided as command line argument

$ python -c 'import sys,re;print("".join(re.split("[-_]",sys.argv[1])[2:]))' "tSA_15_20161014_11-12-50"
20161014111250

Similar approach with ruby:

$ ruby -ne 'puts $_.split(/[-_]/)[2..-1].join("")' <<<  "tSA_15_20161014_11-12-50"                                                   
20161014111250
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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