0

I'm not good at bash shell scripting in Ubuntu, so I need your help.

The problem is...

We use Perforce for SCM.

I try to get directories from //Development/ branches.

Until this time, everything was good.

But now I can't split branches by whitespace anymore, because of branches such as the following (note the embedded space):

//Development/graphic/release/Unity Provider

We need each branch on a separate line starting with //Development, but always I get the following result (note the unwanted line break):

//Development/graphic/release/Unity
Provider

How can I fix this?

Please help me. Thank you.

Below is a sample one-line string:

//Development/graphic/release/CM //Development/graphic/release/GManager //Development/graphic/release/Notification //Development/graphic/release/Core //Development/graphic/release/Provider //Development/graphic/release/WH //Development/graphic/release/Accessory //Development/graphic/release/Unity Provider //Development/graphic/release/tipManager

And, I want to get a result string like below (each branch name on its own line):

//Development/graphic/release/CM 
//Development/graphic/release/GManager 
//Development/graphic/release/Notification 
//Development/graphic/release/Core 
//Development/graphic/release/Provider 
//Development/graphic/release/WH 
//Development/graphic/release/Accessory 
//Development/graphic/release/Unity Provider 
//Development/graphic/release/tipManager

I also want to store the results in a list variable.

E.g., list[0] should contain //Development/graphic/release/CM.

mklement0
  • 382,024
  • 64
  • 607
  • 775
JH5774
  • 31
  • 1
  • 5

3 Answers3

1

I'm assuming that:

  • you want to split your input string into individual paths based on substrings starting with //[Development/], either at the start of the string, or, if inside, preceded by a single space.
  • regardless of whether the strings between //[Development/] instances contain spaces or not.
str='//Development/graphic/release/CM //Development/graphic/release/GManager //Development/graphic/release/Notification //Development/graphic/release/Core //Development/graphic/release/Provider //Development/graphic/release/WH //Development/graphic/release/Accessory //Development/graphic/release/Unity Provider //Development/graphic/release/tipManager'    

echo "$str" | sed 's# \(//\)#\'$'\n''\1#g'

The above should work with any POSIX-compatible sed implementation.

To capture the output in a variable, using command substitution:

result=$(echo "$str" | sed 's# \(//\)#\'$'\n''\1#g')

If you then want to process the result line by line:

while read -r path; do echo "$path"; done <<<"$result"

Explanation of the sed command:

  • # was - arbitrarily - chosen as the delimiter for sed's s (string substitution) command so as to make it easier to match / chars (customarily, / is used as the delimiter, which would necessitate \-escaping / instances in the regex and replacement string).
  •  \(//\) matches // if preceded by a space, i.e., inside the string.
  • \'$'\n'' effectively inserts a newline (\n) into the replacement string, using ANSI C quoting (required for OSX compatibility; on Linux, just \n would do).
  • \1 inserts the 1st (and only) capture group from the regex, i.e, //
  • g ensures that matching is global, i.e., that all substrings that match the regex are replaced.

Result:

//Development/graphic/release/CM
//Development/graphic/release/GManager
//Development/graphic/release/Notification
//Development/graphic/release/Core
//Development/graphic/release/Provider
//Development/graphic/release/WH
//Development/graphic/release/Accessory
//Development/graphic/release/Unity Provider
//Development/graphic/release/tipManager
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Thank you for your help, but I can't use -E option at sed cmd. I think this os is redhat – JH5774 Jun 19 '14 at 05:06
  • @user3754723: I see. I've just updated my answer to make it POSIX-compatible, which should work for you - let me know if it doesn't. – mklement0 Jun 19 '14 at 05:09
  • Thank you very much, and... I have one more question...:) How can I store it to variable? list=`echo "$str" | sed 's# \(//\)#\'$'\n''\1#g'` It doesn't work I want. I want to store it to list. – JH5774 Jun 19 '14 at 05:18
  • @user3754723 You're welcome; re capturing output in a variable: see my update. – mklement0 Jun 19 '14 at 05:23
  • Well, I still have to get same result :( `for element in $result do echo $element done` Sorry, I can't comment beautyfully using new line :( – JH5774 Jun 19 '14 at 05:31
  • @user3754723: `for` is not the right tool for this (it splits on spaces, too, and has other pitfalls); use `while`: `while read -r path; do echo "$path"; done <<<"$result"` – mklement0 Jun 19 '14 at 05:33
0

Use the Internal Field Separator (IFS) Variable to break on newline instead of white space.

This explains it well: http://mindspill.net/computing/linux-notes/using-the-bash-ifs-variable-to-make-for-loops-split-with-non-whitespace-characters/

An example pulled from the link above:

#!/bin/bash
IFS=$','
vals='/mnt,/var/lib/vmware/Virtual Machines,/dev,/proc,/sys,/tmp,/usr/portage,/var/tmp'
for i in $vals; 
     do echo $i; 
done
unset IFS
obi1
  • 314
  • 2
  • 6
  • Re terminology: Newlines are also a form of whitespace (white space). The OP's sample input is a _one-line_ string, so splitting by newlines does not apply. – mklement0 Jun 19 '14 at 05:02
0

You could try this awk command also,

$ awk -v RS=" //" '{gsub (/^D/,"//D");}1' file
//Development/graphic/release/CM
//Development/graphic/release/GManager
//Development/graphic/release/Notification
//Development/graphic/release/Core
//Development/graphic/release/Provider
//Development/graphic/release/WH
//Development/graphic/release/Accessory
//Development/graphic/release/Unity Provider
//Development/graphic/release/tipManager 
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
  • No No~ I want to do that like below: //Development/graphic/release/CM //Development/graphic/release/GManager //Development/graphic/release/Notification //Development/graphic/release/Core //Development/graphic/release/Provider //Development/graphic/release/WH //Development/graphic/release/Accessory //Development/graphic/release/Unity Provider //Development/graphic/release/tipManager – JH5774 Jun 19 '14 at 05:02
  • post the above comment in your question. – Avinash Raj Jun 19 '14 at 05:07