How to Format a String in Bash Shell

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



Leave a reply



Submit