views:

47

answers:

3

Say I have a bash array (e.g. the array of all parameters) and want to delete all parameters matching a certain pattern or alternatively copy all remaining elements to a new array. Alternatively, the other way round, keep elements matching a pattern.

An example for illustration:

x=(preffoo bar foo prefbaz baz prefbar)

and I want to delete everything starting with pref in order to get

y=(bar foo baz)

(the order is not relevant)

What if I want the same thing for a list of words separated by whitespace?

x="preffoo bar foo prefbaz baz prefbar"

and again delete everything starting with pref in order to get

y="bar foo baz"
+2  A: 

u can do this

     Delete all occurrences of substring.
     # Not specifing a replacement defaults to 'delete' ...
       echo ${x[@]//pref*/}      # one two three four ve ve
       #               ^^          # Applied to all elements of the array.

Edit:

for white space its kind of same

                 x="preffoo bar foo prefbaz baz prefbar"
        localhost$ echo ${x[@]//pref*/}
           output: bar foo baz 
Hulk
Anything similar for a string of words separated by whitespace?
kynan
see the edit...
Hulk
Seems that doesn't quite work, that removes everything after the first occurrence of `pref`
kynan
look at my workaround.Or i didnt understand your question
Hulk
Are you using bash? I tried there very same and got an empty output
kynan
why is that there is a specific requirement for bash?Cant u use /bin/sh
Hulk
No, it's not. But I think camh pointed out why it worked for your case.
kynan
+1  A: 

To strip a flat string (Hulk has already given the answer for arrays), you can turn on the extglob shell option and run the following expansion

$ shopt -s extglob
$ unset x
$ x="preffoo bar foo prefbaz baz prefbar"
$ echo ${x//pref*([^ ])?( )}
bar foo baz

The extglob option is needed for the *(pattern-list) and ?(pattern-list) forms. This allows you to use regular expressions (although in a different form to most regular expressions) instead of just pathname expansion (*?[).

The answer that Hulk has given for arrays will work only on arrays. If it appears to work on flat strings, its only because in testing the array was not unset first.

e.g.

$ x=(preffoo bar foo prefbaz baz prefbar)
$ echo ${x[@]//pref*/}
bar foo baz
$ x="preffoo bar foo prefbaz baz prefbar"
$ echo ${x[@]//pref*/}
bar foo baz
$ unset x
$ x="preffoo bar foo prefbaz baz prefbar"
$ echo ${x[@]//pref*/}

$
camh
+1 thanks for clearing up the confusion from Hulk's post and pointing out this other path.
kynan
+1  A: 

Another way to strip a flat string is to convert it to an array then use the array method:

x="preffoo bar foo prefbaz baz prefbar"
x=($x)
x={$x[@]//pref*}

Contrast this with starting and ending with an array:

x=(preffoo bar foo prefbaz baz prefbar)
x=({$x[@]//pref*})
Dennis Williamson