tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: interactive shell detection in shrc



    Date:        Fri, 27 Sep 2024 01:32:34 +0200
    From:        Steffen Nurpmeso <steffen%sdaoden.eu@localhost>
    Message-ID:  <20240926233234.MwKivWJi@steffen%sdaoden.eu>

  | Yes i am afraid of shell field splitting and expansion, and i do
  | not understand why eg
  |
  |   a() {
  |           echo $#,1="$1"/$1,2="$2"/$2,3="$3"/$3,4="$4"/$4,5="$5"/$5,6="$6"/$6,'*'="$*"/$*,'@'="$@",$@
  |           echo $#,1= "$1" , $1 , 2= "$2" , $2 , 3= "$3" , $3 , 4= "$4" , $4 , 5= "$5" , $5 , 6= "$6" , $6 , '*=' "$*" , $* , '@=' "$@" , $@
  |   }
  |   set -- '' '' ''
  |   a "$*"$* $*
  |
  | ...
  |
  |   -1,1=  / ,2=/,3=/,4=/,5=/,6=/,*=  / ,@=  ,$
  |           ^
  |
  | there is this space, whereas

$1 (unquoted) is 2 space, field splitting separates the word at that point,
what comes before is the first arg to echo, what follows (until the next field
split) is the second.   When echo writes its args it inserts a space between
them.   That is where that space comes from.

  |   -1,1=    , , 2=  , , 3=  , , 4=  , , 5=  , , 6=  , , *=    , , @=    ,$
  |             ^
  | here there is it not (that is bash, but dash ditto).

Almost identical reasoning (which shell should affect nothing there).

$1 is two spaces, those get field split into absolutely nothing.
Then the args to that echo are (one to a line here)

	$#,1=
	"$1"		(ie: '  ')
	,
	,		(the intervening unquoted $1 has vanished)
	2=
	"$2"		(what that is depends upon the shell, as it depends how $* is expanded)
	,

	(etc)

echo writes those args, separated by spaces.  The space you marked is the space
echo inserted between the 3 & 4th args (the consecutive commas).

If you really want to see what the args are, don't use echo, and *don't*
include any expansion unquoted in your "a" function, that just confuses things.

Instead use (something like):

	a()
	{
		printf %s: "$#"
		printf '<%s>' "$@"
		printf \\n
	}

That will make what is in each arg very clear.   But sorry, to do it this
easy way you'll have to count the <xxx> strings to see which is which.

You could replace the middle line by

		N=0
		for A
		do
			N=$((N + 1))
			printf ' %s:<%s>' "$N" "$A"
		done

and then you'll get more like

	2: 1:<aaa> 2:<bbb>

if run as "a aaa bbb"

kre


Home | Main Index | Thread Index | Old Index