(Bash) Editing contents of array from within function
Clash Royale CLAN TAG#URR8PPP
up vote
4
down vote
favorite
I'm trying to pad all the items of an array to 20 characters with whitespace, but can't seem to get my loop to work properly. It appears to increment through the array items correctly, but does not alter the items. Where am I going wrong here?
#!/bin/bash
testArray=( "bish" "bash" "bosh")
padLine ()
array=( "$@" )
testLength=20
counter=0
##loop begins here##
for i in "$array[@]";
do
size=$#array[$counter]
testLength=20
#echo ""
#echo "size: " $size
#echo "Tlength: " $testLength
#echo "count: " $array[$counter]
#echo ""
if [ $size -lt $testLength ]
then
offset=$( expr $testLength - $size )
#echo "Offset: " $offset
case $offset in
0)
l0=""
;;
1)
l1=" "
array[$counter]=$array[$counter]/%/$l1;;
2)
l2=" "
array[$counter]="$array[$counter]/%/$l2";;
3)
l3=" "
array[$counter]=$array[$counter]/%/$l3;;
4)
l4=" "
array[$counter]="$array[$counter]/%/$l4";;
5)
l5=" "
array[$counter]="$array[$counter]/%/$l5";;
6)
l6=" "
array[$counter]=$array[$counter]/%/$l6;;
7)
l7=" "
array[$counter]=$array[$counter]/%/$l7;;
8)
l8=" "
array[$counter]=$array[$counter]/%/$l8;;
9)
l9=" "
array[$counter]=$array[$counter]/%/$l9;;
10)
l10=" "
array[$counter]=$array[$counter]/%/$l10;;
11)
l11=" "
array[$counter]=$array[$counter]/%/$l11;;
12)
l12=" "
array[$counter]=$array[$counter]/%/$l12;;
13)
l13=" "
array[$counter]=$array[$counter]/%/$l13;;
14)
l14=" "
array[$counter]=$array[$counter]/%/$l14;;
15)
l15=" "
array[$counter]=$array[$counter]/%/$l15;;
16)
l16=" "
array[$counter]=$array[$counter]/%/$l16;;
17)
l17=" "
array[$counter]=$array[$counter]/%/$l17;;
18)
l18=" "
array[$counter]=$array[$counter]/%/$l18;;
19)
l19=" "
array[$counter]=$array[$counter]/%/$l19;;
*)
esac
fi
counter=$( expr $counter + 1 )
done
padLine "$testArray[@]"
echo -e "$testArray[0]"
echo -e "$testArray[1]"
echo -e "$testArray[2]"
Expected output:
bish #lines end here, padded to 20 chars
bash #
bosh #
Actual output:
bish# no padding
bash
bosh
bash shell-script
add a comment |Â
up vote
4
down vote
favorite
I'm trying to pad all the items of an array to 20 characters with whitespace, but can't seem to get my loop to work properly. It appears to increment through the array items correctly, but does not alter the items. Where am I going wrong here?
#!/bin/bash
testArray=( "bish" "bash" "bosh")
padLine ()
array=( "$@" )
testLength=20
counter=0
##loop begins here##
for i in "$array[@]";
do
size=$#array[$counter]
testLength=20
#echo ""
#echo "size: " $size
#echo "Tlength: " $testLength
#echo "count: " $array[$counter]
#echo ""
if [ $size -lt $testLength ]
then
offset=$( expr $testLength - $size )
#echo "Offset: " $offset
case $offset in
0)
l0=""
;;
1)
l1=" "
array[$counter]=$array[$counter]/%/$l1;;
2)
l2=" "
array[$counter]="$array[$counter]/%/$l2";;
3)
l3=" "
array[$counter]=$array[$counter]/%/$l3;;
4)
l4=" "
array[$counter]="$array[$counter]/%/$l4";;
5)
l5=" "
array[$counter]="$array[$counter]/%/$l5";;
6)
l6=" "
array[$counter]=$array[$counter]/%/$l6;;
7)
l7=" "
array[$counter]=$array[$counter]/%/$l7;;
8)
l8=" "
array[$counter]=$array[$counter]/%/$l8;;
9)
l9=" "
array[$counter]=$array[$counter]/%/$l9;;
10)
l10=" "
array[$counter]=$array[$counter]/%/$l10;;
11)
l11=" "
array[$counter]=$array[$counter]/%/$l11;;
12)
l12=" "
array[$counter]=$array[$counter]/%/$l12;;
13)
l13=" "
array[$counter]=$array[$counter]/%/$l13;;
14)
l14=" "
array[$counter]=$array[$counter]/%/$l14;;
15)
l15=" "
array[$counter]=$array[$counter]/%/$l15;;
16)
l16=" "
array[$counter]=$array[$counter]/%/$l16;;
17)
l17=" "
array[$counter]=$array[$counter]/%/$l17;;
18)
l18=" "
array[$counter]=$array[$counter]/%/$l18;;
19)
l19=" "
array[$counter]=$array[$counter]/%/$l19;;
*)
esac
fi
counter=$( expr $counter + 1 )
done
padLine "$testArray[@]"
echo -e "$testArray[0]"
echo -e "$testArray[1]"
echo -e "$testArray[2]"
Expected output:
bish #lines end here, padded to 20 chars
bash #
bosh #
Actual output:
bish# no padding
bash
bosh
bash shell-script
add a comment |Â
up vote
4
down vote
favorite
up vote
4
down vote
favorite
I'm trying to pad all the items of an array to 20 characters with whitespace, but can't seem to get my loop to work properly. It appears to increment through the array items correctly, but does not alter the items. Where am I going wrong here?
#!/bin/bash
testArray=( "bish" "bash" "bosh")
padLine ()
array=( "$@" )
testLength=20
counter=0
##loop begins here##
for i in "$array[@]";
do
size=$#array[$counter]
testLength=20
#echo ""
#echo "size: " $size
#echo "Tlength: " $testLength
#echo "count: " $array[$counter]
#echo ""
if [ $size -lt $testLength ]
then
offset=$( expr $testLength - $size )
#echo "Offset: " $offset
case $offset in
0)
l0=""
;;
1)
l1=" "
array[$counter]=$array[$counter]/%/$l1;;
2)
l2=" "
array[$counter]="$array[$counter]/%/$l2";;
3)
l3=" "
array[$counter]=$array[$counter]/%/$l3;;
4)
l4=" "
array[$counter]="$array[$counter]/%/$l4";;
5)
l5=" "
array[$counter]="$array[$counter]/%/$l5";;
6)
l6=" "
array[$counter]=$array[$counter]/%/$l6;;
7)
l7=" "
array[$counter]=$array[$counter]/%/$l7;;
8)
l8=" "
array[$counter]=$array[$counter]/%/$l8;;
9)
l9=" "
array[$counter]=$array[$counter]/%/$l9;;
10)
l10=" "
array[$counter]=$array[$counter]/%/$l10;;
11)
l11=" "
array[$counter]=$array[$counter]/%/$l11;;
12)
l12=" "
array[$counter]=$array[$counter]/%/$l12;;
13)
l13=" "
array[$counter]=$array[$counter]/%/$l13;;
14)
l14=" "
array[$counter]=$array[$counter]/%/$l14;;
15)
l15=" "
array[$counter]=$array[$counter]/%/$l15;;
16)
l16=" "
array[$counter]=$array[$counter]/%/$l16;;
17)
l17=" "
array[$counter]=$array[$counter]/%/$l17;;
18)
l18=" "
array[$counter]=$array[$counter]/%/$l18;;
19)
l19=" "
array[$counter]=$array[$counter]/%/$l19;;
*)
esac
fi
counter=$( expr $counter + 1 )
done
padLine "$testArray[@]"
echo -e "$testArray[0]"
echo -e "$testArray[1]"
echo -e "$testArray[2]"
Expected output:
bish #lines end here, padded to 20 chars
bash #
bosh #
Actual output:
bish# no padding
bash
bosh
bash shell-script
I'm trying to pad all the items of an array to 20 characters with whitespace, but can't seem to get my loop to work properly. It appears to increment through the array items correctly, but does not alter the items. Where am I going wrong here?
#!/bin/bash
testArray=( "bish" "bash" "bosh")
padLine ()
array=( "$@" )
testLength=20
counter=0
##loop begins here##
for i in "$array[@]";
do
size=$#array[$counter]
testLength=20
#echo ""
#echo "size: " $size
#echo "Tlength: " $testLength
#echo "count: " $array[$counter]
#echo ""
if [ $size -lt $testLength ]
then
offset=$( expr $testLength - $size )
#echo "Offset: " $offset
case $offset in
0)
l0=""
;;
1)
l1=" "
array[$counter]=$array[$counter]/%/$l1;;
2)
l2=" "
array[$counter]="$array[$counter]/%/$l2";;
3)
l3=" "
array[$counter]=$array[$counter]/%/$l3;;
4)
l4=" "
array[$counter]="$array[$counter]/%/$l4";;
5)
l5=" "
array[$counter]="$array[$counter]/%/$l5";;
6)
l6=" "
array[$counter]=$array[$counter]/%/$l6;;
7)
l7=" "
array[$counter]=$array[$counter]/%/$l7;;
8)
l8=" "
array[$counter]=$array[$counter]/%/$l8;;
9)
l9=" "
array[$counter]=$array[$counter]/%/$l9;;
10)
l10=" "
array[$counter]=$array[$counter]/%/$l10;;
11)
l11=" "
array[$counter]=$array[$counter]/%/$l11;;
12)
l12=" "
array[$counter]=$array[$counter]/%/$l12;;
13)
l13=" "
array[$counter]=$array[$counter]/%/$l13;;
14)
l14=" "
array[$counter]=$array[$counter]/%/$l14;;
15)
l15=" "
array[$counter]=$array[$counter]/%/$l15;;
16)
l16=" "
array[$counter]=$array[$counter]/%/$l16;;
17)
l17=" "
array[$counter]=$array[$counter]/%/$l17;;
18)
l18=" "
array[$counter]=$array[$counter]/%/$l18;;
19)
l19=" "
array[$counter]=$array[$counter]/%/$l19;;
*)
esac
fi
counter=$( expr $counter + 1 )
done
padLine "$testArray[@]"
echo -e "$testArray[0]"
echo -e "$testArray[1]"
echo -e "$testArray[2]"
Expected output:
bish #lines end here, padded to 20 chars
bash #
bosh #
Actual output:
bish# no padding
bash
bosh
bash shell-script
asked Jun 13 at 12:26
user19923311885
211
211
add a comment |Â
add a comment |Â
6 Answers
6
active
oldest
votes
up vote
6
down vote
Just for output:
array=( bish bash bosh )
printf '%-20s#n' "$array[@]"
This would produce
bish #
bash #
bosh #
... where #
occurs in column 21.
To make a new array (and printing it):
array=( bish bash bosh )
for elem in "$array[@]"; do
padarr+=( "$( printf '%-20s#' "$elem" )" )
done
printf '%sn' "$padarr[@]"
With /bin/sh
, just printing:
set -- bish bash bosh
printf '%-20s#n' "$@"
With /bin/sh
, modifying $@
in-place:
set -- bish bash bosh
i=0
while [ "$i" -lt "$#" ]; do
set -- "$@" "$( printf '%-20s#' "$1" )"
shift
i=$(( i + 1 ))
done
printf '%sn' "$@"
The printf
formatting string %-20s
reserves 20 characters for a left-justified string.
As a bash
(4.3+) function:
pad_array ()
local padlen=$1
local -n localarray=$2
local -a tmp
local elem
for elem in "$localarray[@]"; do
tmp+=( "$( printf '%-*s#' "$padlen" "$elem" )" )
done
localarray=( "$tmp[@]" )
myarray=( bish bash bosh )
pad_array 20 myarray
printf '%sn' "$myarray[@]"
The pad_array
function here additionally allows you to choose the amount of padding.
The array is passed by its name and is received by the function in a name reference variable. This means that whenever the name reference is accessed in the function, the named variable are actually used.
2
Note thatprintf %-20s
pads to 20 bytes, not characters inbash
which would make a different for multi-byte characters. See alsoprintf -v
inbash
to avoid the cmdsubst.
â Stéphane Chazelas
Jun 13 at 13:08
Note that the nameref variant could change the indices of the array. An array defined asa([5]=x [12]=y)
would end up asa([0]="x ..." [1]="y ...")
â Stéphane Chazelas
Jun 13 at 13:43
add a comment |Â
up vote
4
down vote
If switching to zsh
is an option:
$ array=(foo bar bÃÂ z '')
$ padded_array=($(r:20:)array)
$ printf '<%s>n' $padded_array
<foo >
<bar >
<bÃÂ z >
< >
Note that that (r:20:)
right-padding parameter expansion flag pads but also truncates to 20 characters for strings that are longer.
Another option with zsh
is to do:
padded_array=()
(($#array)) && printf -v padded_array '%-20s' "$array[@]"
Contrary to bash
, the padding is done character-wise as opposed to byte-wise and zsh
supports array arguments to the -v
option.
Note that if $array
contains just one element, $padded_array
is converted to scalar.
For padding+truncating, replace %-20s
with %-20.20s
.
add a comment |Â
up vote
1
down vote
You're doing two mistakes.
You're passing
testArray
to the function, then you create the new array in the function, you modify it, but you finally print out the first array. You want to print the modified results, right?Your script doesn't do what you expect, because you use this construct:
array[$counter]=$array[$counter]/%/$l16
This is the pattern substitution of general form
$parameter/pattern/string
. You don't need to substitute anything. You have the suffix ready at this point, just need to append it like:array[$counter]="$array[$counter]$l16"
You can access the array array
outside of the function, as the array is not declared as local. So you can just use:
echo -e "$array[0]"
etc.
add a comment |Â
up vote
1
down vote
To pass variables by reference in bash
4.3+, you can use typeset -n
:
pad_array()
typeset -n _array="$1"
typeset _n="$2" _pad _i
printf -v _pad '%*s' "$_n"
for _i in "$!_array[@]"; do
(($#_array[_i] < _n))
array=(foo b bÃÂ z '')
pad_array array 20
The typeset -n
nameref feature comes from ksh93
however note that contrary to in ksh93
, the above won't work to pad array variables whose name is used in the function (hence the underscore prefix for them to limit the risk of clashing).
add a comment |Â
up vote
0
down vote
If youâÂÂre willing to place an arbitrary upper limit
on the number of spaces to add
(and you obviously are,
as your case
statement canâÂÂt handle a length greater than 20),
and youâÂÂre just talking about bytes
(and not characters, which can be multi-byte),
a simple way to pad a variable to a given length is:
# 75 spaces
spaces=" "
ï¸Â
length=20
ï¸Â
newValue=$(expr substr "$value$spaces" 1 "$length")
add a comment |Â
up vote
0
down vote
Core idea
for elem in "$localarrayname[@]"; do
localtoarray+=( "$(printf '<%-*.*s>n' "$p" "$p" "$elem")" )
done
Simple var
Using printf to add a variable count of spaces is very simple (the asterisk is the count):
$ printf '<%-*s>' 8 hello ; echo
<hello >
It could even be used to either extend or cut an string to a count:
$ printf '<%-*.*s>' 8 8 "TestingHello" ; echo
<TestingH>
Fixed trailing string
Using variable substitution we can add a fixed string to a variable:
$ var=hello
$ printf '<%s>n' "$var/%/"xxx""
<helloxxx>
That could be expanded to an array of values:
$ var=( hello world test )
$ printf '<%s>n' "$var[@]/%/"xxx""
<helloxxx>
<worldxxx>
<testxxx>
Array of values.
However, to add a variable count of spaces to an array we need to use a loop.
We can use a function to pass the list of values (only printing):
padarray() p=$1; shift
for elem; do
printf '<%-*.*s>n' "$p" "$p" "$elem"
done
array=( foo qux quuux alongerstring )
padarray 15 "$array[@]"
It prints:
$ ./script
<foo >
<qux >
<quuux >
<alongerstringto>
Indirect array.
To pass the arguments to a new array using the array(s) names (indirect):
padarray() local p=$1;
local -n localarrayname=$2 localtoarray=$3
localtoarray=()
for elem in "$localarrayname[@]"; do
localtoarray+=( "$(printf '<%-*.*s>n' "$p" "$p" "$elem")" )
done
array=( foo qux quuux alongerstringtotest )
padarray 12 array paddedarray
printf '%sn' "$paddedarray[@]"
Which on execution prints a similar result:
$ ./script
<foo >
<qux >
<quuux >
<alongerstrin>
Better pad count.
Adding a more robust count number of padding characters ($p
):
p=$1//[!0-9] # Select only numeric digits.
(( 0<=p && p<=999 )) && return 2 # Return on error. Count out of range.
Final
We end with this script:
#!/bin/bash
padarray()
array=( bash bish bosh "" foo qux quuux "A Longer String To Test" )
padarray 20 array paddedarray
printf '%sn' "$paddedarray[@]"
add a comment |Â
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
6
down vote
Just for output:
array=( bish bash bosh )
printf '%-20s#n' "$array[@]"
This would produce
bish #
bash #
bosh #
... where #
occurs in column 21.
To make a new array (and printing it):
array=( bish bash bosh )
for elem in "$array[@]"; do
padarr+=( "$( printf '%-20s#' "$elem" )" )
done
printf '%sn' "$padarr[@]"
With /bin/sh
, just printing:
set -- bish bash bosh
printf '%-20s#n' "$@"
With /bin/sh
, modifying $@
in-place:
set -- bish bash bosh
i=0
while [ "$i" -lt "$#" ]; do
set -- "$@" "$( printf '%-20s#' "$1" )"
shift
i=$(( i + 1 ))
done
printf '%sn' "$@"
The printf
formatting string %-20s
reserves 20 characters for a left-justified string.
As a bash
(4.3+) function:
pad_array ()
local padlen=$1
local -n localarray=$2
local -a tmp
local elem
for elem in "$localarray[@]"; do
tmp+=( "$( printf '%-*s#' "$padlen" "$elem" )" )
done
localarray=( "$tmp[@]" )
myarray=( bish bash bosh )
pad_array 20 myarray
printf '%sn' "$myarray[@]"
The pad_array
function here additionally allows you to choose the amount of padding.
The array is passed by its name and is received by the function in a name reference variable. This means that whenever the name reference is accessed in the function, the named variable are actually used.
2
Note thatprintf %-20s
pads to 20 bytes, not characters inbash
which would make a different for multi-byte characters. See alsoprintf -v
inbash
to avoid the cmdsubst.
â Stéphane Chazelas
Jun 13 at 13:08
Note that the nameref variant could change the indices of the array. An array defined asa([5]=x [12]=y)
would end up asa([0]="x ..." [1]="y ...")
â Stéphane Chazelas
Jun 13 at 13:43
add a comment |Â
up vote
6
down vote
Just for output:
array=( bish bash bosh )
printf '%-20s#n' "$array[@]"
This would produce
bish #
bash #
bosh #
... where #
occurs in column 21.
To make a new array (and printing it):
array=( bish bash bosh )
for elem in "$array[@]"; do
padarr+=( "$( printf '%-20s#' "$elem" )" )
done
printf '%sn' "$padarr[@]"
With /bin/sh
, just printing:
set -- bish bash bosh
printf '%-20s#n' "$@"
With /bin/sh
, modifying $@
in-place:
set -- bish bash bosh
i=0
while [ "$i" -lt "$#" ]; do
set -- "$@" "$( printf '%-20s#' "$1" )"
shift
i=$(( i + 1 ))
done
printf '%sn' "$@"
The printf
formatting string %-20s
reserves 20 characters for a left-justified string.
As a bash
(4.3+) function:
pad_array ()
local padlen=$1
local -n localarray=$2
local -a tmp
local elem
for elem in "$localarray[@]"; do
tmp+=( "$( printf '%-*s#' "$padlen" "$elem" )" )
done
localarray=( "$tmp[@]" )
myarray=( bish bash bosh )
pad_array 20 myarray
printf '%sn' "$myarray[@]"
The pad_array
function here additionally allows you to choose the amount of padding.
The array is passed by its name and is received by the function in a name reference variable. This means that whenever the name reference is accessed in the function, the named variable are actually used.
2
Note thatprintf %-20s
pads to 20 bytes, not characters inbash
which would make a different for multi-byte characters. See alsoprintf -v
inbash
to avoid the cmdsubst.
â Stéphane Chazelas
Jun 13 at 13:08
Note that the nameref variant could change the indices of the array. An array defined asa([5]=x [12]=y)
would end up asa([0]="x ..." [1]="y ...")
â Stéphane Chazelas
Jun 13 at 13:43
add a comment |Â
up vote
6
down vote
up vote
6
down vote
Just for output:
array=( bish bash bosh )
printf '%-20s#n' "$array[@]"
This would produce
bish #
bash #
bosh #
... where #
occurs in column 21.
To make a new array (and printing it):
array=( bish bash bosh )
for elem in "$array[@]"; do
padarr+=( "$( printf '%-20s#' "$elem" )" )
done
printf '%sn' "$padarr[@]"
With /bin/sh
, just printing:
set -- bish bash bosh
printf '%-20s#n' "$@"
With /bin/sh
, modifying $@
in-place:
set -- bish bash bosh
i=0
while [ "$i" -lt "$#" ]; do
set -- "$@" "$( printf '%-20s#' "$1" )"
shift
i=$(( i + 1 ))
done
printf '%sn' "$@"
The printf
formatting string %-20s
reserves 20 characters for a left-justified string.
As a bash
(4.3+) function:
pad_array ()
local padlen=$1
local -n localarray=$2
local -a tmp
local elem
for elem in "$localarray[@]"; do
tmp+=( "$( printf '%-*s#' "$padlen" "$elem" )" )
done
localarray=( "$tmp[@]" )
myarray=( bish bash bosh )
pad_array 20 myarray
printf '%sn' "$myarray[@]"
The pad_array
function here additionally allows you to choose the amount of padding.
The array is passed by its name and is received by the function in a name reference variable. This means that whenever the name reference is accessed in the function, the named variable are actually used.
Just for output:
array=( bish bash bosh )
printf '%-20s#n' "$array[@]"
This would produce
bish #
bash #
bosh #
... where #
occurs in column 21.
To make a new array (and printing it):
array=( bish bash bosh )
for elem in "$array[@]"; do
padarr+=( "$( printf '%-20s#' "$elem" )" )
done
printf '%sn' "$padarr[@]"
With /bin/sh
, just printing:
set -- bish bash bosh
printf '%-20s#n' "$@"
With /bin/sh
, modifying $@
in-place:
set -- bish bash bosh
i=0
while [ "$i" -lt "$#" ]; do
set -- "$@" "$( printf '%-20s#' "$1" )"
shift
i=$(( i + 1 ))
done
printf '%sn' "$@"
The printf
formatting string %-20s
reserves 20 characters for a left-justified string.
As a bash
(4.3+) function:
pad_array ()
local padlen=$1
local -n localarray=$2
local -a tmp
local elem
for elem in "$localarray[@]"; do
tmp+=( "$( printf '%-*s#' "$padlen" "$elem" )" )
done
localarray=( "$tmp[@]" )
myarray=( bish bash bosh )
pad_array 20 myarray
printf '%sn' "$myarray[@]"
The pad_array
function here additionally allows you to choose the amount of padding.
The array is passed by its name and is received by the function in a name reference variable. This means that whenever the name reference is accessed in the function, the named variable are actually used.
edited Jun 13 at 12:59
answered Jun 13 at 12:41
Kusalananda
101k13199312
101k13199312
2
Note thatprintf %-20s
pads to 20 bytes, not characters inbash
which would make a different for multi-byte characters. See alsoprintf -v
inbash
to avoid the cmdsubst.
â Stéphane Chazelas
Jun 13 at 13:08
Note that the nameref variant could change the indices of the array. An array defined asa([5]=x [12]=y)
would end up asa([0]="x ..." [1]="y ...")
â Stéphane Chazelas
Jun 13 at 13:43
add a comment |Â
2
Note thatprintf %-20s
pads to 20 bytes, not characters inbash
which would make a different for multi-byte characters. See alsoprintf -v
inbash
to avoid the cmdsubst.
â Stéphane Chazelas
Jun 13 at 13:08
Note that the nameref variant could change the indices of the array. An array defined asa([5]=x [12]=y)
would end up asa([0]="x ..." [1]="y ...")
â Stéphane Chazelas
Jun 13 at 13:43
2
2
Note that
printf %-20s
pads to 20 bytes, not characters in bash
which would make a different for multi-byte characters. See also printf -v
in bash
to avoid the cmdsubst.â Stéphane Chazelas
Jun 13 at 13:08
Note that
printf %-20s
pads to 20 bytes, not characters in bash
which would make a different for multi-byte characters. See also printf -v
in bash
to avoid the cmdsubst.â Stéphane Chazelas
Jun 13 at 13:08
Note that the nameref variant could change the indices of the array. An array defined as
a([5]=x [12]=y)
would end up as a([0]="x ..." [1]="y ...")
â Stéphane Chazelas
Jun 13 at 13:43
Note that the nameref variant could change the indices of the array. An array defined as
a([5]=x [12]=y)
would end up as a([0]="x ..." [1]="y ...")
â Stéphane Chazelas
Jun 13 at 13:43
add a comment |Â
up vote
4
down vote
If switching to zsh
is an option:
$ array=(foo bar bÃÂ z '')
$ padded_array=($(r:20:)array)
$ printf '<%s>n' $padded_array
<foo >
<bar >
<bÃÂ z >
< >
Note that that (r:20:)
right-padding parameter expansion flag pads but also truncates to 20 characters for strings that are longer.
Another option with zsh
is to do:
padded_array=()
(($#array)) && printf -v padded_array '%-20s' "$array[@]"
Contrary to bash
, the padding is done character-wise as opposed to byte-wise and zsh
supports array arguments to the -v
option.
Note that if $array
contains just one element, $padded_array
is converted to scalar.
For padding+truncating, replace %-20s
with %-20.20s
.
add a comment |Â
up vote
4
down vote
If switching to zsh
is an option:
$ array=(foo bar bÃÂ z '')
$ padded_array=($(r:20:)array)
$ printf '<%s>n' $padded_array
<foo >
<bar >
<bÃÂ z >
< >
Note that that (r:20:)
right-padding parameter expansion flag pads but also truncates to 20 characters for strings that are longer.
Another option with zsh
is to do:
padded_array=()
(($#array)) && printf -v padded_array '%-20s' "$array[@]"
Contrary to bash
, the padding is done character-wise as opposed to byte-wise and zsh
supports array arguments to the -v
option.
Note that if $array
contains just one element, $padded_array
is converted to scalar.
For padding+truncating, replace %-20s
with %-20.20s
.
add a comment |Â
up vote
4
down vote
up vote
4
down vote
If switching to zsh
is an option:
$ array=(foo bar bÃÂ z '')
$ padded_array=($(r:20:)array)
$ printf '<%s>n' $padded_array
<foo >
<bar >
<bÃÂ z >
< >
Note that that (r:20:)
right-padding parameter expansion flag pads but also truncates to 20 characters for strings that are longer.
Another option with zsh
is to do:
padded_array=()
(($#array)) && printf -v padded_array '%-20s' "$array[@]"
Contrary to bash
, the padding is done character-wise as opposed to byte-wise and zsh
supports array arguments to the -v
option.
Note that if $array
contains just one element, $padded_array
is converted to scalar.
For padding+truncating, replace %-20s
with %-20.20s
.
If switching to zsh
is an option:
$ array=(foo bar bÃÂ z '')
$ padded_array=($(r:20:)array)
$ printf '<%s>n' $padded_array
<foo >
<bar >
<bÃÂ z >
< >
Note that that (r:20:)
right-padding parameter expansion flag pads but also truncates to 20 characters for strings that are longer.
Another option with zsh
is to do:
padded_array=()
(($#array)) && printf -v padded_array '%-20s' "$array[@]"
Contrary to bash
, the padding is done character-wise as opposed to byte-wise and zsh
supports array arguments to the -v
option.
Note that if $array
contains just one element, $padded_array
is converted to scalar.
For padding+truncating, replace %-20s
with %-20.20s
.
edited Jun 13 at 13:19
answered Jun 13 at 13:12
Stéphane Chazelas
279k53513844
279k53513844
add a comment |Â
add a comment |Â
up vote
1
down vote
You're doing two mistakes.
You're passing
testArray
to the function, then you create the new array in the function, you modify it, but you finally print out the first array. You want to print the modified results, right?Your script doesn't do what you expect, because you use this construct:
array[$counter]=$array[$counter]/%/$l16
This is the pattern substitution of general form
$parameter/pattern/string
. You don't need to substitute anything. You have the suffix ready at this point, just need to append it like:array[$counter]="$array[$counter]$l16"
You can access the array array
outside of the function, as the array is not declared as local. So you can just use:
echo -e "$array[0]"
etc.
add a comment |Â
up vote
1
down vote
You're doing two mistakes.
You're passing
testArray
to the function, then you create the new array in the function, you modify it, but you finally print out the first array. You want to print the modified results, right?Your script doesn't do what you expect, because you use this construct:
array[$counter]=$array[$counter]/%/$l16
This is the pattern substitution of general form
$parameter/pattern/string
. You don't need to substitute anything. You have the suffix ready at this point, just need to append it like:array[$counter]="$array[$counter]$l16"
You can access the array array
outside of the function, as the array is not declared as local. So you can just use:
echo -e "$array[0]"
etc.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
You're doing two mistakes.
You're passing
testArray
to the function, then you create the new array in the function, you modify it, but you finally print out the first array. You want to print the modified results, right?Your script doesn't do what you expect, because you use this construct:
array[$counter]=$array[$counter]/%/$l16
This is the pattern substitution of general form
$parameter/pattern/string
. You don't need to substitute anything. You have the suffix ready at this point, just need to append it like:array[$counter]="$array[$counter]$l16"
You can access the array array
outside of the function, as the array is not declared as local. So you can just use:
echo -e "$array[0]"
etc.
You're doing two mistakes.
You're passing
testArray
to the function, then you create the new array in the function, you modify it, but you finally print out the first array. You want to print the modified results, right?Your script doesn't do what you expect, because you use this construct:
array[$counter]=$array[$counter]/%/$l16
This is the pattern substitution of general form
$parameter/pattern/string
. You don't need to substitute anything. You have the suffix ready at this point, just need to append it like:array[$counter]="$array[$counter]$l16"
You can access the array array
outside of the function, as the array is not declared as local. So you can just use:
echo -e "$array[0]"
etc.
answered Jun 13 at 13:08
Tomasz
8,03052560
8,03052560
add a comment |Â
add a comment |Â
up vote
1
down vote
To pass variables by reference in bash
4.3+, you can use typeset -n
:
pad_array()
typeset -n _array="$1"
typeset _n="$2" _pad _i
printf -v _pad '%*s' "$_n"
for _i in "$!_array[@]"; do
(($#_array[_i] < _n))
array=(foo b bÃÂ z '')
pad_array array 20
The typeset -n
nameref feature comes from ksh93
however note that contrary to in ksh93
, the above won't work to pad array variables whose name is used in the function (hence the underscore prefix for them to limit the risk of clashing).
add a comment |Â
up vote
1
down vote
To pass variables by reference in bash
4.3+, you can use typeset -n
:
pad_array()
typeset -n _array="$1"
typeset _n="$2" _pad _i
printf -v _pad '%*s' "$_n"
for _i in "$!_array[@]"; do
(($#_array[_i] < _n))
array=(foo b bÃÂ z '')
pad_array array 20
The typeset -n
nameref feature comes from ksh93
however note that contrary to in ksh93
, the above won't work to pad array variables whose name is used in the function (hence the underscore prefix for them to limit the risk of clashing).
add a comment |Â
up vote
1
down vote
up vote
1
down vote
To pass variables by reference in bash
4.3+, you can use typeset -n
:
pad_array()
typeset -n _array="$1"
typeset _n="$2" _pad _i
printf -v _pad '%*s' "$_n"
for _i in "$!_array[@]"; do
(($#_array[_i] < _n))
array=(foo b bÃÂ z '')
pad_array array 20
The typeset -n
nameref feature comes from ksh93
however note that contrary to in ksh93
, the above won't work to pad array variables whose name is used in the function (hence the underscore prefix for them to limit the risk of clashing).
To pass variables by reference in bash
4.3+, you can use typeset -n
:
pad_array()
typeset -n _array="$1"
typeset _n="$2" _pad _i
printf -v _pad '%*s' "$_n"
for _i in "$!_array[@]"; do
(($#_array[_i] < _n))
array=(foo b bÃÂ z '')
pad_array array 20
The typeset -n
nameref feature comes from ksh93
however note that contrary to in ksh93
, the above won't work to pad array variables whose name is used in the function (hence the underscore prefix for them to limit the risk of clashing).
edited Jun 13 at 14:12
answered Jun 13 at 13:33
Stéphane Chazelas
279k53513844
279k53513844
add a comment |Â
add a comment |Â
up vote
0
down vote
If youâÂÂre willing to place an arbitrary upper limit
on the number of spaces to add
(and you obviously are,
as your case
statement canâÂÂt handle a length greater than 20),
and youâÂÂre just talking about bytes
(and not characters, which can be multi-byte),
a simple way to pad a variable to a given length is:
# 75 spaces
spaces=" "
ï¸Â
length=20
ï¸Â
newValue=$(expr substr "$value$spaces" 1 "$length")
add a comment |Â
up vote
0
down vote
If youâÂÂre willing to place an arbitrary upper limit
on the number of spaces to add
(and you obviously are,
as your case
statement canâÂÂt handle a length greater than 20),
and youâÂÂre just talking about bytes
(and not characters, which can be multi-byte),
a simple way to pad a variable to a given length is:
# 75 spaces
spaces=" "
ï¸Â
length=20
ï¸Â
newValue=$(expr substr "$value$spaces" 1 "$length")
add a comment |Â
up vote
0
down vote
up vote
0
down vote
If youâÂÂre willing to place an arbitrary upper limit
on the number of spaces to add
(and you obviously are,
as your case
statement canâÂÂt handle a length greater than 20),
and youâÂÂre just talking about bytes
(and not characters, which can be multi-byte),
a simple way to pad a variable to a given length is:
# 75 spaces
spaces=" "
ï¸Â
length=20
ï¸Â
newValue=$(expr substr "$value$spaces" 1 "$length")
If youâÂÂre willing to place an arbitrary upper limit
on the number of spaces to add
(and you obviously are,
as your case
statement canâÂÂt handle a length greater than 20),
and youâÂÂre just talking about bytes
(and not characters, which can be multi-byte),
a simple way to pad a variable to a given length is:
# 75 spaces
spaces=" "
ï¸Â
length=20
ï¸Â
newValue=$(expr substr "$value$spaces" 1 "$length")
edited Jun 14 at 1:37
answered Jun 13 at 21:59
Scott
6,21332347
6,21332347
add a comment |Â
add a comment |Â
up vote
0
down vote
Core idea
for elem in "$localarrayname[@]"; do
localtoarray+=( "$(printf '<%-*.*s>n' "$p" "$p" "$elem")" )
done
Simple var
Using printf to add a variable count of spaces is very simple (the asterisk is the count):
$ printf '<%-*s>' 8 hello ; echo
<hello >
It could even be used to either extend or cut an string to a count:
$ printf '<%-*.*s>' 8 8 "TestingHello" ; echo
<TestingH>
Fixed trailing string
Using variable substitution we can add a fixed string to a variable:
$ var=hello
$ printf '<%s>n' "$var/%/"xxx""
<helloxxx>
That could be expanded to an array of values:
$ var=( hello world test )
$ printf '<%s>n' "$var[@]/%/"xxx""
<helloxxx>
<worldxxx>
<testxxx>
Array of values.
However, to add a variable count of spaces to an array we need to use a loop.
We can use a function to pass the list of values (only printing):
padarray() p=$1; shift
for elem; do
printf '<%-*.*s>n' "$p" "$p" "$elem"
done
array=( foo qux quuux alongerstring )
padarray 15 "$array[@]"
It prints:
$ ./script
<foo >
<qux >
<quuux >
<alongerstringto>
Indirect array.
To pass the arguments to a new array using the array(s) names (indirect):
padarray() local p=$1;
local -n localarrayname=$2 localtoarray=$3
localtoarray=()
for elem in "$localarrayname[@]"; do
localtoarray+=( "$(printf '<%-*.*s>n' "$p" "$p" "$elem")" )
done
array=( foo qux quuux alongerstringtotest )
padarray 12 array paddedarray
printf '%sn' "$paddedarray[@]"
Which on execution prints a similar result:
$ ./script
<foo >
<qux >
<quuux >
<alongerstrin>
Better pad count.
Adding a more robust count number of padding characters ($p
):
p=$1//[!0-9] # Select only numeric digits.
(( 0<=p && p<=999 )) && return 2 # Return on error. Count out of range.
Final
We end with this script:
#!/bin/bash
padarray()
array=( bash bish bosh "" foo qux quuux "A Longer String To Test" )
padarray 20 array paddedarray
printf '%sn' "$paddedarray[@]"
add a comment |Â
up vote
0
down vote
Core idea
for elem in "$localarrayname[@]"; do
localtoarray+=( "$(printf '<%-*.*s>n' "$p" "$p" "$elem")" )
done
Simple var
Using printf to add a variable count of spaces is very simple (the asterisk is the count):
$ printf '<%-*s>' 8 hello ; echo
<hello >
It could even be used to either extend or cut an string to a count:
$ printf '<%-*.*s>' 8 8 "TestingHello" ; echo
<TestingH>
Fixed trailing string
Using variable substitution we can add a fixed string to a variable:
$ var=hello
$ printf '<%s>n' "$var/%/"xxx""
<helloxxx>
That could be expanded to an array of values:
$ var=( hello world test )
$ printf '<%s>n' "$var[@]/%/"xxx""
<helloxxx>
<worldxxx>
<testxxx>
Array of values.
However, to add a variable count of spaces to an array we need to use a loop.
We can use a function to pass the list of values (only printing):
padarray() p=$1; shift
for elem; do
printf '<%-*.*s>n' "$p" "$p" "$elem"
done
array=( foo qux quuux alongerstring )
padarray 15 "$array[@]"
It prints:
$ ./script
<foo >
<qux >
<quuux >
<alongerstringto>
Indirect array.
To pass the arguments to a new array using the array(s) names (indirect):
padarray() local p=$1;
local -n localarrayname=$2 localtoarray=$3
localtoarray=()
for elem in "$localarrayname[@]"; do
localtoarray+=( "$(printf '<%-*.*s>n' "$p" "$p" "$elem")" )
done
array=( foo qux quuux alongerstringtotest )
padarray 12 array paddedarray
printf '%sn' "$paddedarray[@]"
Which on execution prints a similar result:
$ ./script
<foo >
<qux >
<quuux >
<alongerstrin>
Better pad count.
Adding a more robust count number of padding characters ($p
):
p=$1//[!0-9] # Select only numeric digits.
(( 0<=p && p<=999 )) && return 2 # Return on error. Count out of range.
Final
We end with this script:
#!/bin/bash
padarray()
array=( bash bish bosh "" foo qux quuux "A Longer String To Test" )
padarray 20 array paddedarray
printf '%sn' "$paddedarray[@]"
add a comment |Â
up vote
0
down vote
up vote
0
down vote
Core idea
for elem in "$localarrayname[@]"; do
localtoarray+=( "$(printf '<%-*.*s>n' "$p" "$p" "$elem")" )
done
Simple var
Using printf to add a variable count of spaces is very simple (the asterisk is the count):
$ printf '<%-*s>' 8 hello ; echo
<hello >
It could even be used to either extend or cut an string to a count:
$ printf '<%-*.*s>' 8 8 "TestingHello" ; echo
<TestingH>
Fixed trailing string
Using variable substitution we can add a fixed string to a variable:
$ var=hello
$ printf '<%s>n' "$var/%/"xxx""
<helloxxx>
That could be expanded to an array of values:
$ var=( hello world test )
$ printf '<%s>n' "$var[@]/%/"xxx""
<helloxxx>
<worldxxx>
<testxxx>
Array of values.
However, to add a variable count of spaces to an array we need to use a loop.
We can use a function to pass the list of values (only printing):
padarray() p=$1; shift
for elem; do
printf '<%-*.*s>n' "$p" "$p" "$elem"
done
array=( foo qux quuux alongerstring )
padarray 15 "$array[@]"
It prints:
$ ./script
<foo >
<qux >
<quuux >
<alongerstringto>
Indirect array.
To pass the arguments to a new array using the array(s) names (indirect):
padarray() local p=$1;
local -n localarrayname=$2 localtoarray=$3
localtoarray=()
for elem in "$localarrayname[@]"; do
localtoarray+=( "$(printf '<%-*.*s>n' "$p" "$p" "$elem")" )
done
array=( foo qux quuux alongerstringtotest )
padarray 12 array paddedarray
printf '%sn' "$paddedarray[@]"
Which on execution prints a similar result:
$ ./script
<foo >
<qux >
<quuux >
<alongerstrin>
Better pad count.
Adding a more robust count number of padding characters ($p
):
p=$1//[!0-9] # Select only numeric digits.
(( 0<=p && p<=999 )) && return 2 # Return on error. Count out of range.
Final
We end with this script:
#!/bin/bash
padarray()
array=( bash bish bosh "" foo qux quuux "A Longer String To Test" )
padarray 20 array paddedarray
printf '%sn' "$paddedarray[@]"
Core idea
for elem in "$localarrayname[@]"; do
localtoarray+=( "$(printf '<%-*.*s>n' "$p" "$p" "$elem")" )
done
Simple var
Using printf to add a variable count of spaces is very simple (the asterisk is the count):
$ printf '<%-*s>' 8 hello ; echo
<hello >
It could even be used to either extend or cut an string to a count:
$ printf '<%-*.*s>' 8 8 "TestingHello" ; echo
<TestingH>
Fixed trailing string
Using variable substitution we can add a fixed string to a variable:
$ var=hello
$ printf '<%s>n' "$var/%/"xxx""
<helloxxx>
That could be expanded to an array of values:
$ var=( hello world test )
$ printf '<%s>n' "$var[@]/%/"xxx""
<helloxxx>
<worldxxx>
<testxxx>
Array of values.
However, to add a variable count of spaces to an array we need to use a loop.
We can use a function to pass the list of values (only printing):
padarray() p=$1; shift
for elem; do
printf '<%-*.*s>n' "$p" "$p" "$elem"
done
array=( foo qux quuux alongerstring )
padarray 15 "$array[@]"
It prints:
$ ./script
<foo >
<qux >
<quuux >
<alongerstringto>
Indirect array.
To pass the arguments to a new array using the array(s) names (indirect):
padarray() local p=$1;
local -n localarrayname=$2 localtoarray=$3
localtoarray=()
for elem in "$localarrayname[@]"; do
localtoarray+=( "$(printf '<%-*.*s>n' "$p" "$p" "$elem")" )
done
array=( foo qux quuux alongerstringtotest )
padarray 12 array paddedarray
printf '%sn' "$paddedarray[@]"
Which on execution prints a similar result:
$ ./script
<foo >
<qux >
<quuux >
<alongerstrin>
Better pad count.
Adding a more robust count number of padding characters ($p
):
p=$1//[!0-9] # Select only numeric digits.
(( 0<=p && p<=999 )) && return 2 # Return on error. Count out of range.
Final
We end with this script:
#!/bin/bash
padarray()
array=( bash bish bosh "" foo qux quuux "A Longer String To Test" )
padarray 20 array paddedarray
printf '%sn' "$paddedarray[@]"
answered Jun 14 at 7:59
Isaac
6,3041632
6,3041632
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f449535%2fbash-editing-contents-of-array-from-within-function%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password