1

How to capture only the sdX from the following line using bash, awk, sed or perl in one liner command?

echo ""dfs.datanode.data.dir" : "/rid/sdb/oo/hdfs/data,/rid/sdc/oo/hdfs/data,/rid/sdd/oo/hdfs/data,/rid/sde/oo/hdfs/data,/rid/sdf/oo/hdfs/data","

expected output

sdb
sdc
sdd
sde
sdf
  • You can get that output with printf '%s\n' sdb sdc sdd sde sdf. If you want a more general answer, please explain what you want, in general.  Do you want to extract the sdg from /dev/sdg, or only after /rid/? What if the input contains sd1, sd17, or sda17? How about open("/dev/sd#"); would you want sd# (i.e., including the next character after sd, even if it’s not alphanumeric)? How about words like “disdain”, “wisdom”, “eavesdrop”, “transduce”, “jurisdiction”, “misdeed”, “Tuesday”, “Wednesday” and “Thursday” (which contain “sd”)? How about “freebsd” (which ends with “sd”)? – G-Man Apr 6 at 15:56
  • This looks like it could be from a JSON file. Are you able to share a larger portion of the file? – Kusalananda Apr 7 at 13:13
2

You can use GREP arguments:

   -P, --perl-regexp
          Interpret the pattern as a Perl-compatible regular expression
          (PCRE).  This is experimental and grep -P may warn of
          unimplemented features.
   -o, --only-matching
          Print only the matched (non-empty) parts of a matching line,
          with each such part on a separate output line.

So your command would be:

echo ""dfs.datanode.data.dir" : "/rid/sdb/oo/hdfs/data,/rid/sdc/oo/hdfs/data,/rid/sdd/oo/hdfs/data,/rid/sde/oo/hdfs/data,/rid/sdf/oo/hdfs/data"," | grep -oP "\w*sd\w*"
sdb
sdc
sdd
sde
sdf
  • 1
    Sorry, you talk about the option -P and the you use -h to hide the filename? grep is (in this case) reading from stdin – FaxMax Dec 22 '17 at 10:48
  • Corrected, wrong copy/paste. Thanks. – Kevin Lemaire Dec 22 '17 at 10:52
1

Use

echo ... | grep -Eo "sd[a-z]"

where -E interprets the pattern as an (extended) regular expression and -o prints only the matching parts in each line.

  • 1
    That’s not an extended regular expression;  that command will work without the E option. – G-Man Apr 6 at 14:29
0
echo '"dfs.datanode.data.dir" : "/rid/sdb/oo/hdfs/data,/rid/sdc/oo/hdfs/data,/rid/sdd/oo/hdfs/data,/rid/sde/oo/hdfs/data,/rid/sdf/oo/hdfs/data",' 
"dfs.datanode.data.dir" : "/rid/sdb/oo/hdfs/data,/rid/sdc/oo/hdfs/data,/rid/sdd/oo/hdfs/data,/rid/sde/oo/hdfs/data,/rid/sdf/oo/hdfs/data",
echo '"dfs.datanode.data.dir" : "/rid/sdb/oo/hdfs/data,/rid/sdc/oo/hdfs/data,/rid/sdd/oo/hdfs/data,/rid/sde/oo/hdfs/data,/rid/sdf/oo/hdfs/data",' | grep -Po 'sd\w'
sdb
sdc
sdd
sde
sdf
0

You did not specify what x should be in sdX so one could as well assume that it might be any character:

$ echo echo ""dfs.datanode.data.dir" : "/rid/sdb/oo/hdfs/data,/rid/sdc/oo/hdfs/data,/rid/sdd/oo/hdfs/data,/rid/sde/oo/hdfs/data,/rid/sdf/oo/hdfs /data"," | grep -o 'sd.'
sdb
sdc
sdd
sde
sdf

A literal . means any character in regular expressions.

And in perl because you wanted that explicitly:

$ echo ""dfs.datanode.data.dir" : "/rid/sdb/oo/hdfs/data,/rid/sdc/oo/hdfs/data,/rid/sdd/oo/hdfs/data,/rid/sde/oo/hdfs/data,/rid/sdf/oo/hdfs/data"," | perl -nE 'say $& while /sd./g'
sdb
sdc
sdd
sde
sdf
0

gnu sed:

$ s='"dfs.datanode.data.dir" : "/rid/sdb/oo/hdfs/data,/rid/sdc/oo/hdfs/data,/rid/sdd/oo/hdfs/data,/rid/sde/oo/hdfs/data,/rid/sdf/oo/hdfs/data",'

$ echo $s| sed -E ':b;s~[^,:]+.{,3}/rid/(.+)~\1~;Te;h;s~(\w+)/.*~\1~p;g;tb;:e d'
  • I do not get it – Pierre.Vriens Apr 6 at 13:55
  • (1) You might not be able to tell from the previous answers to this question, but we prefer answers to explain how they work — especially when they’re as complicated as this one, and when they are added to a long list of other answers, long after the question was asked.  (2) Your command produces the correct expected result for the sample input.  So does printf '%s\n' sdb sdc sdd sde sdf.  Of course that wouldn’t be an acceptable answer; it would work only for the sample input, and essentially nothing else.  … (Cont’d) – G-Man Apr 6 at 15:28
  • (Cont’d) … My point is that the same is true of your answer.  The question says “capture only the sdX …”; you have made many assumptions about the input, in general, assuming that it will look very very much like the sample input.  It is necessary to make some assumptions about what the questioner wants, because the question is terribly vague.  But you should state what assumptions you are making, especially when they are as broad as the ones you are making. – G-Man Apr 6 at 15:28
0

Above result is achieved by awk one liner

Done by below command

echo ""dfs.datanode.data.dir" : "/rid/sdb/oo/hdfs/data,/rid/sdc/oo/hdfs/data,/rid/sdd/oo/hdfs/data,/rid/sde/oo/hdfs/data,/rid/sdf/oo/hdfs/data","|perl -pne "s/,/\n/g"| sed '/^$/d'| awk -F "/" '{print $3}'

output

echo ""dfs.datanode.data.dir" : "/rid/sdb/oo/hdfs/data,/rid/sdc/oo/hdfs/data,/rid/sdd/oo/hdfs/data,/rid/sde/oo/hdfs/data,/rid/sdf/oo/hdfs/data","|perl -pne "s/,/\n/g"| sed '/^$/d'| awk -F "/" '{print $3}'
sdb
sdc
sdd
sde
sdf
praveen@praveen:~$

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.