string formatting in bash
Is _
supposed to be a placeholder that is sometimes a different character?
In bash
, "input$i\_now"
with an actual _
will always produce input1\_now
. Inside double-quotes, bash
only removes a \
when it is followed by a $
, a `
, a "
, a \
, or a newline. See “Double Quotes” in the Bash Reference Manual. This is the POSIX standard behavior; see “Double-Quotes” in Shell Command Language.
UPDATE
If you write "input$i_now"
, bash
will just print input
. It will not print input1
or input1_now
. It does this because _
is a valid parameter name character, so bash
thinks you are asking for the value of the i_now
parameter. Unless you have set i_now
to a non-empty string, bash
will expand $i_now
to the empty string, thus turning "input$i_now"
into input
.
UPDATE 2
Now that you have posted real code, we can see what's going on.
First of all, in the real code you posted, you never used double-quotes around a parameter expansion. This makes a difference.
Outside of double-quotes, a \
is always removed. See “Quote Removal” in the Bash Reference Manual. Hence input$i\_now
(with no surrounding double-quotes) expands to input1_now
.
However, as I explained in my first update, _
is a parameter name character. See “Name” in Shell Command Language. So when bash
sees input$i_now
, it takes i_now
as the parameter name.
Whether or not you're using double-quotes, you must separate the parameter name from the following character, if bash
would otherwise treat the following character as part of the parameter name. You can do this by putting \
after the parameter name, or you can do it by putting the parameter name in {...}
.
It is safer to always use {...}
, because (as you have discovered?) \
is handled differently depending on whether it's inside double-quotes. If you go back and add double-quotes later, and you have used \
, you will need to change the \
to {...}
anyway.
UPDATE 3
Here is a demonstration of the effects of \
, {...}
, and double-quoting. First, we set up some variables:
$ year=2004 ptime=1 i=1 sim=123
Here's what happens with no quoting whatsoever:
$ echo vect=sim$sim_pts_$year_$ptime_run$i@expSim$sim_$i,sim$sim_pts_$year_$ptime
vect=sim1@expSim1,sim1
Here's what happens if we just use {...}
without double-quotes:
$ echo vect=sim${sim}_pts_${year}_${ptime}_run${i}@expSim${sim}_${i},sim${sim}_pts_${year}_${ptime}
vect=sim123_pts_2004_1_run1@expSim123_1,sim123_pts_2004_1
If we add double-quotes, they have no effect:
$ echo "vect=sim${sim}_pts_${year}_${ptime}_run${i}@expSim${sim}_${i},sim${sim}_pts_${year}_${ptime}"
vect=sim123_pts_2004_1_run1@expSim123_1,sim123_pts_2004_1
Here's what happens if we just use \
:
$ echo vect=sim$sim\_pts\_$year\_$ptime\_run$i@expSim$sim\_$i,sim$sim\_pts\_$year\_$ptime
vect=sim123_pts_2004_1_run1@expSim123_1,sim123_pts_2004_1
Notice that each \
was removed. The shell removes a \
if it's not quoted.
If we add double-quotes, they prevent the shell from removing each \
:
$ echo "vect=sim$sim\_pts\_$year\_$ptime\_run$i@expSim$sim\_$i,sim$sim\_pts\_$year\_$ptime"
vect=sim123\_pts\_2004\_1\_run1@expSim123\_1,sim123\_pts\_2004\_1
How to format a string in bash shell?
Don't edit your bash script on DOS or Windows. You can run dos2unix
on the bash script. The issue is that Windows uses "\r\n" as a line separator, Linux uses "\n". You can also manually remove the "\r" characters in an editor on Linux.
Bash format string. Substitute placeholders with values.
From printf --help
:
-v var assign the output to shell variable VAR rather than display it on the standard output
So, what you need to do is just:
FMT='<username>%s</username><password>%s</password>'
printf -v VAR "$FMT" user pass
Formatting a string in Unix
Replacing the comma is not a particularly good style.
You can do it like this:
landscape=aws,azure
echo $landscape | awk 'BEGIN{FS=",";OFS=",";suffix="-landscape"}{print $1suffix,$2suffix}'
Output:
aws-landscape,azure-landscape
In the BEGIN
block you set the following variables:
- FS: field separator
- OFS: output field separator
- suffix: you can use a variable here, in case you want to change the text later and don't want to change the text on several places in the code
replace all variables in a $-formatted string in bash
In your example it would be sufficient to use double quotes instead of single quotes. If the variables exist at the time of reading a double quoted string, there is no problem:
abc="FOO"
rst="BAR"
format_base="xyz $abc $rst"
If (for some very complicated reason) you have to specify format_base
before the used variables, you can use things like eval
or bash -c
:
format_base='xyz $abc $rst'
# "load" variables $abc and $rst
format_base_processed=$(eval echo "\"$format_base\"")
Note that the above command has security issues, especially if $format_base
is not specified by you. Example:
format_base='$(injectedCommand)'
format_base_processed=$(eval echo "\"$format_base\"")
Here we will execute echo "$(injectedCommand)"
where injectedCommand
could be anything, for example rm -rf *
(do not try this at home).
bash string formatting within a quote
Try this (see the "'"
):
filename='part-00004-9d2ba62f-496e-4cfd-9001-f40f0e33e927-c000.csv'
curl -X POST -H 'Content-Type: application/json' $CLUSTER -d '{
"source" : "'"s3://blah/$filename"'",
"format" : "csv"
}'
The first "'"
is "double quote symbol for the -d argument, switch single quote escaping off, start double quote escaping". The second "'"
is similar.
Bash run string formatted command in a for loop
First, there's no need for using string formatting to generate code here, or in general -- BashFAQ #50 describes the use cases and better-practice alternatives. This could be as simple as the following:
for j in in "${foo[@]}"; do touch "${j}_file.txt"; done
Second, if you must, do it like so:
printf -v cmd 'touch %q_file.txt; ' "${foo[@]}"
eval "$cmd"
This will set cmd='touch bar_file.txt; touch baz_file.txt '
, and then execute it.
Use of %q
when content is to be later parsed by a shell (as with eval
) ensures that your array elements are formatted in a way that will survive shell-parsing -- so if you had foo=( "name with spaces" 'name with $(rm -rf $HOME) dangerous content' )
, you would be correctly touching 'name with spaces_file.txt'
and 'name with $(rm -rf $HOME) dangerous content_file.txt'
, not executing the dangerous content and touching multiple files based on the spaces.
How can I format string in an array using shell script?
Assuming that you just want to left-pad the numbers with zeroes, this can be done in a single command:
$ printf '%04d\n' "${ADDR[@]}"
0333
4444
0333
0333
4444
0333
0333
Here each number in your array is passed to printf
as a separate argument - it takes care of the formatting for you.
Of course, whether this is suitable or not depends on how your plan on using these numbers.
As an aside, return
is only for indicating whether a routine succeeded or not. As such, it only supports values from 0
to 255
. To output something from a function or command, use standard output/error.
Bash: formatting string in printf
In the shell, printf
is a command and command arguments are separated by spaces, not commas.
Use:
printf "%s : %s ===> %s\n" "$t1" "$t2" "$t3"
The double quotes are necessary too; otherwise the Current Permission
and New Permission
arguments will be split up and you'll get two lines of output from your single printf
command.
I note that your function takes (at least) two arguments, but you do not show those being printed or otherwise used within the function. You may need to revisit that part of your logic.
With your current logic:
t1="RESOURCE"
t2="Current Permission"
t3="New Permission"
printf "%s : %s ===> %s\n",$t1,$t2,$t3
you really pass to printf
:
printf "%s : %s ===> %s\n,RESOURCE,Current" "Permission,New" "Permission"
Note how the 'format string' argument includes all of $t1
and part of $t2
. You only provide two arguments for the three %s
formats, so the third one is left empty. The output is:
Permission,New : Permission ===>
,RESOURCE,Current
with a space at the end of the first line and no newline at the end of the second 'line' (hence your prompt appears immediately after Current
).
Related Topics
How to Use a Samba Server Location for Gopath
Reading Complete Line in 'For' Loop with Spaces, Tabs with Multiple Input Files
Python3 Unicodeencodeerror When Run via Synology Task Scheduler
Escaping Single Quotes in Shell for Postgresql
Synchronize Linux System Clock to Windows Ntp Service
Terminal Closes When I Source My Script (Run with Dot at the Start)
Nginx Location Deny by File Extension Syntax
Hard Time Installing Ia32-Lib on MAC Osx
Bash -Eq and ==, What's the Diff
Elegant Way to Set Base Address of Elf Image with Linux Binutils
Print the Output of Strace Command in a Text File
Why Does Autoconf Erroneously Find a Function Which Isn't Available Later
Bash Shell: Cannot Use Variable $ as a Path to Run Tar
Delete Folder That Contain Subfolders and Files on Linux
Comparing 16 Bit Numbers in Nasm Produces Wrong Results