bobbyiliev / introduction-to-bash-scripting

Free Introduction to Bash Scripting eBook
https://ebook.bobby.sh
MIT License
4.16k stars 415 forks source link

Bug: Substring in Bash :: Slicing - Examples incorrect #153

Closed Skinner927 closed 1 month ago

Skinner927 commented 1 month ago

Describe the bug

The section Substring in Bash :: Slicing, nested under Bash Arrays is not operating on an arrays at all. It should not be nested under the Arrays section.

The letters array in the examples is presumed to be an array with multiple elements. Instead, because there are no spaces, the letters array is an array with a single element.

#!/bin/bash
letters=( "A""B""C""D""E" )
echo ${letters[@]}

In later examples the array is "sliced":

#!/bin/bash
letters=( "A""B""C""D""E" )
b=${letters:0:2}
echo "${b}"
# AB

This command will print array from starting index 0 to 2 where 2 is exclusive.

The text says this is operating on the arrays indexes, but it's actually slicing a string. $letters without an index ([x]) will return index 0 by default, thus the "ABCDE" string.

The examples work almost by accident and are a poor illustration of how to access ranges.

To Reproduce

If letters was actually an array (replaced with real here) the examples would not work.

letters=( "A""B""C""D""E" )
b=${letters:0:2}
echo "${b}"
# AB

real=( "A" "B" "C" "D" "E" )
echo "${real:0:2}"
# A

Expected behavior

I believe the slicing section should be moved out from under the Arrays heading and into a Strings section, or anywhere else.

The examples should change the definition of letters to letters="ABCDE" and no other changes would be needed since these are all string operations.

Screenshots

image

Additional context

bobbyiliev commented 1 month ago

Thank you for this feedback! Very helpful! I'll look into it later on this week.

Love the cat btw!

lewisxy commented 1 month ago

Also, the examples provided and the wording seems to suggest that the second number is the end offset + 1 (similar to python's slice notation). This is not the case. The meaning of the second number is the maximum length of the slice. For example,

a="12345"
echo "${a:3:3}"

will print out 45 since the start index is 3 and the max length is 3 (which became 2 since a has a length of 5).

It will be great if you can stress this point. I only figured out by experimentation.

acoteff commented 1 month ago

To add to this, I believe that the output will not produce the '$' as outlined.

Screenshot 2024-08-01 at 1 39 20 PM
bobbyiliev commented 1 month ago

Just submitted a PR for this:

https://github.com/bobbyiliev/introduction-to-bash-scripting/pull/156

If anyone is interested in reviewing it feel free to do so @Skinner927 @lewisxy @acoteff