WelcomeWelcome | FAQFAQ | DownloadsDownloads | WikiWiki

Author Topic: Proposal: improve provides.sh to wget provides.db.gz, instead of provides.db  (Read 3229 times)

Offline Greg Erskine

  • Sr. Member
  • ****
  • Posts: 404
Code: [Select]
DB="provides.db"

"$MIRROR"/"$DB".zsync

Can I ask opinions about the formatting of the filename "$DB".zsync ?

options?

1. "$DB".zsync
2. "$DB.zsync"
3. "${DB}.zsync"

All work fine, I tend to use 3.

Offline GNUser

  • Wiki Author
  • Hero Member
  • *****
  • Posts: 1496
POSIX shells use space as field separator. Variable names must match the regex [a-zA-Z_][a-zA-Z0-9_]* (i.e., must start with a letter or underscore, followed by zero or more letters/digits/underscores). (So wacky variable names such as _ or _1 are technically permissible--if ill-advised.)

$foo is shorthand for ${foo} and the two are interchangeable most of the time. If the variable is followed by a character that is allowed to be part of a variable name, then you need ${foo} to prevent ambiguity. You can never go wrong with ${foo} but it's not needed here--shell does not allow a period to be part of variable name, so there is no ambiguity in $foo.extension

${foo}.bar and "${foo}.bar" are interchangeable unless the value of ${foo} contains a space, in which case the shell would get confused and interpret the value of ${foo}.bar as two separate things (delimited by the space inside the variable foo).

Bottomline:
From the code snipped we know that DB does not contain a space, so quotes are not required. What follows the variable name (a period) cannot be confused for being part of the variable name, so curly brackets are also not required. So all three forms you listed are fine. I've seen forms #1 and #2 in TCL scripts. Personally I'd go with #2 because it avoids me having to type the unnecessary curly brackets (vs. #3) and it would still work if the value of DB were to change in the future to include a space (vs. #1).

« Last Edit: February 28, 2023, 04:11:51 PM by GNUser »

Offline nick65go

  • Hero Member
  • *****
  • Posts: 832
@GNUser: very nice lessons for shell, [sh]. Good to have them here for quick reference.

Offline GNUser

  • Wiki Author
  • Hero Member
  • *****
  • Posts: 1496
I did some tests. If var contains a space, "$var".zsync and "$var.zsync" both work. The shell sees both as a single argument. Only $var.zsync (without any quotes) would be a problem because it would be seen as two arguments.

I've been shell programming for over a decade and just learned something new today :)

Gentlemen, the three forms are completely interchangeable. Form #3 just has two extra characters.
« Last Edit: February 28, 2023, 05:17:45 PM by GNUser »

Offline Greg Erskine

  • Sr. Member
  • ****
  • Posts: 404
Thanks for the feedback.

Offline Rich

  • Administrator
  • Hero Member
  • *****
  • Posts: 11573
Hi GNUser
While my preference is to wrap  $VAR+text  references in quotes, I have run
into some corner cases where the shell thinks the variable is called  VARtext.

I think it might have been when  VAR  ended in or  text  had a leading  -  or  _

Nowadays I first  echo "$VARtext"  to make sure it behaves the way I expect
it to, or just write it as  "$VAR"text  out of caution.

Offline GNUser

  • Wiki Author
  • Hero Member
  • *****
  • Posts: 1496
Hi Rich. I also generally wrap all of $VARtext in quotes, but you are right (as usual) in saying this will fail in rare corner cases.

"${VAR}text" would always work. "$VAR"text would also always work. "$VARtext" will only fail in the corner case where text has a leading alphanumeric character or underscore. (If text has a leading hyphen or period, no problem because the shell would never interpret those characters as being part of the variable name.)
« Last Edit: March 01, 2023, 10:44:47 AM by GNUser »

Offline Greg Erskine

  • Sr. Member
  • ****
  • Posts: 404
Which why I use like to use "${VAR}text" even if there is a period as the first text character. To me, it's like aways putting double quotes around a variable name if it is a string.

I have been caught out before and it's not always easy to see.