Skip to main content
added 575 characters in body
Source Link
Stéphane Chazelas
  • 584.6k
  • 96
  • 1.1k
  • 1.7k

If switching to zsh is an option (that array=(values) syntax actually comes from zsh), then it's just a matter of:

intersection=( ${A:*B} )
subtraction=( ${A:|B} )

Or if the arrays may contain empty values and you want to preserve them, use the @ parameter expansion flag and double quotes (like for the Bourne shell's "$@"):

intersection=( "${(@)A:*B}" )

See typeset -U intersection to make the elements unique in the array. Or use the u parameter expansion flag to remove duplicates upon expansion.

${A:*B} expands to the elements of $A that are also found in $B. If the elements are not unique, then it's not necessarily the same as ${B:*A}. For instance, with A=(x x x) B=(x x), ${A:*B} yields x x x, while ${B:*A} yields x x. Even with distinct elements, the order may be different.

Example:

$ a=( a b c '' b c a '' ) b=( c B A '' A c b '')
$ i1=( ${a:*b} ) i2=( "${(@)a:*b}" ) i3=( "${(@u)a:*b}" ) s=( ${a:|b} )
$ typeset i{1..3} s
i1=( b c b c )
i2=( b c '' b c '' )
i3=( b c '' )
s=( a a )

If switching to zsh is an option (that array=(values) syntax actually comes from zsh), then it's just a matter of:

intersection=( ${A:*B} )

Or if the arrays may contain empty values and you want to preserve them:

intersection=( "${(@)A:*B}" )

See typeset -U intersection to make the elements unique in the array. Or use the u parameter expansion flag to remove duplicates upon expansion.

If switching to zsh is an option (that array=(values) syntax actually comes from zsh), then it's just a matter of:

intersection=( ${A:*B} )
subtraction=( ${A:|B} )

Or if the arrays may contain empty values and you want to preserve them, use the @ parameter expansion flag and double quotes (like for the Bourne shell's "$@"):

intersection=( "${(@)A:*B}" )

See typeset -U intersection to make the elements unique in the array. Or use the u parameter expansion flag to remove duplicates upon expansion.

${A:*B} expands to the elements of $A that are also found in $B. If the elements are not unique, then it's not necessarily the same as ${B:*A}. For instance, with A=(x x x) B=(x x), ${A:*B} yields x x x, while ${B:*A} yields x x. Even with distinct elements, the order may be different.

Example:

$ a=( a b c '' b c a '' ) b=( c B A '' A c b '')
$ i1=( ${a:*b} ) i2=( "${(@)a:*b}" ) i3=( "${(@u)a:*b}" ) s=( ${a:|b} )
$ typeset i{1..3} s
i1=( b c b c )
i2=( b c '' b c '' )
i3=( b c '' )
s=( a a )
Source Link
Stéphane Chazelas
  • 584.6k
  • 96
  • 1.1k
  • 1.7k

If switching to zsh is an option (that array=(values) syntax actually comes from zsh), then it's just a matter of:

intersection=( ${A:*B} )

Or if the arrays may contain empty values and you want to preserve them:

intersection=( "${(@)A:*B}" )

See typeset -U intersection to make the elements unique in the array. Or use the u parameter expansion flag to remove duplicates upon expansion.