How to resolve arithmetic syntax error in printf - linux

I am running below code in SunOS as .sh file
#!/usr/bin/bash
#lerning linux scripting
#
printf "%-5s %-10s %-4s\n" No Name Mark
printf "%-5s %-10s %-4.2f\n" 1 James 80.1234
printf "%-5s %-10s %-4.2f\n" 2 Sarah 99.8923
But I am getting below error when run above one in SunOS
No Name Mark
: arithmetic syntax error.sh[5]: printf: 80.1234
: arithmetic syntax error0.1234
linux_sc.sh[5]: printf: warning: invalid argument of type f
80.12
: arithmetic syntax error.sh[6]: printf: 99.8923
: arithmetic syntax error9.8923
linux_sc.sh[6]: printf: warning: invalid argument of type f
99.89

So yeah, pretty sure you're using a script that has Windows style CRLF line endings, while Unix systems use LF. This happens when you write the file on Windows and don't transfer it to the other computer in a way that translates line endings.
Taking your sample script and running it through unix2dos and then trying to run it gives:
No Name Mark
: invalid numberprintf: 80.1234
1 James 0.00
: invalid numberprintf: 99.8923
2 Sarah 0.00
Not exactly the same output, but I'm testing on Linux, not SunOS, so that's to be expected. Close enough, though, to suggest it's the issue.
If you have dos2unix installed on the SunOS box, run your script through it and see if that fixes the problem. Or perl -pi -e 's/\r//' your.sh is another way of stripping the extraneous carriage returns. Or tr -d '\r' < your.sh > new.sh or any number of other ways; just depends on what a typical SunOS setup has installed. I haven't used it in years; don't remember off the top of my head.

Related

How do I specify the position of a width parameter?

Apologies if this has been posted before. I've been searching all over and can't find an answer.
According to man printf, "FORMAT controls the output as in C printf." It refers to printf(3).
According to man 3 printf, you can specify a variable width in a given position. It says:
Instead of a decimal digit string one may write … "*m$" (for some decimal integer m) to specify that the precision is given in the m-th argument … which must be of type int.
This is the part where I'm struggling. To give a simple example, suppose I wish to print a string with width 14.
$ printf '[%14s]\n' Something
[ Something]
I can use a variable instead:
$ WIDTH=14
$ printf '[%*s]\n' ${WIDTH} Something
[ Something]
The tricky part comes when I want to tell printf that the width argument is in a different position. To keep things simple for this example, I'll leave it where it is, in position 1. Following the instructions, I write the following.
Built-in version:
$ printf '[%*1$s]\n' ${WIDTH} Something
bash: printf: `1': invalid format character
Version in /usr/bin:
$ /usr/bin/printf '[%*1$s]\n' ${WIDTH} Something
[/usr/bin/printf: %*1: invalid conversion specification
Even using the example from the manual gives an error.
Built-in version:
$ printf '%2$*1$d' 6 34
bash: printf: `$': invalid format character
Version in /usr/bin:
$ /usr/bin/printf '%2$*1$d' 6 34
/usr/bin/printf: %2$: invalid conversion specification
As you can see, I get an error every time. I have struggled to see what I'm doing wrong, and I simply cannot find any example online.
How should this be formatted, please, or is the manual just wrong?
Lubuntu 18.04
GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
builtin printf: unknown version
/usr/bin/printf printf (GNU coreutils) 8.28
Thank you
No, the extension that comes from Single UNIX Specification to C printf function to specify the position of positional parameter with $ is not supported in bash printf and I doubt it's supported in any of shells printf implementations. I believe the reason is that it requires additional work from the developers, while it's very rarely used extension.
is the manual just wrong?
FORMAT controls the output as in C printf.
You are reading the documentation for GNU version of printf, taken from the amazing Linux man-pages project. I would say C printf is documented in the C standard.
If your shell's printf doesn't support parameter indexing, you can still call Perl to the rescue!
$ perl -we 'printf q([%1$*2$d]), #ARGV' 36 6
[ 36]
See printf and, more importantly, sprintf.

Concatenating string read from file with string literals creates jumbled output

My problem is that the result is jumbled. Consider this script:
#!/bin/bash
INPUT="filelist.txt"
i=0;
while read label
do
i=$[$i+1]
echo "HELLO${label}WORLD"
done <<< $'1\n2\n3\n4'
i=0;
while read label
do
i=$[$i+1]
echo "HELLO${label}WORLD"
done < "$INPUT"
filelist.txt
5
8
15
67
...
The first loop, with the immediate input (through something I believe is called a herestring (the <<< operator) gives the expected output
HELLO1WORLD
HELLO2WORLD
HELLO3WORLD
HELLO4WORLD
The second loop, which reads from the file, gives the following jumbled output:
WORLD5
WORLD8
WORLD15
WORLD67
I've tried echo $label: This works as expected in both cases, but the concatenation fails in the second case as described. Further, the exact same code works on my Win 7, git-bash environment. This issue is on OSX 10.7 Lion.
How to concatenate strings in bash |
Bash variables concatenation |
concat string in a shell script
Well, just as I was about to hit post, the solution hit me. Sharing here so someone else can find it - it took me 3 hours to debug this (despite being on SO for almost all that time) so I see value in addressing this specific (common) use case.
The problem is that filelist.txt was created in Windows. This means it has CRLF line endings, while OSX (like other Unix-like environments) expects LF only line endings. (See more here: Difference between CR LF, LF and CR line break types?)
I used the answer here to convert the file before consumption. Using sed I managed to replace only the final line's carriage return, so I stuck to known guns and went for the perl approach. Final script is below:
#!/bin/bash
INPUTFILE="filelist.txt"
INPUT=$(perl -pe 's/\r\n|\n|\r/\n/g' "$INPUTFILE")
i=0;
while read label
do
i=$[$i+1]
echo "HELLO${label}WORLD"
done <<< $'INPUT'
Question has been asked in a different form at Bash: Concatenating strings fails when read from certain files

What does "cat -A" command option mean in Unix

I'm currently working on a Unix box and came across this post which I found helpful, in order to learn about cat command in Unix. At the bottom of the page found this line saying: -A = Equivalent to -vET
As I'm new into Unix, I'm unaware of what does this mean actually? For example lets say I've created a file called new using cat and then apply this command to the file:
cat -A new, I tried this command but an error message comes up saying it's and illegal option.
To cut short, wanted to know what does cat -A really mean and how does it effect when I apply it to a file. Any help would be appreciated.
It means show ALL.
Basically its a combination of -vET
E : It will display '$' at the end of every line.
T : It will display tab character as ^I
v : It will use ^ and M-notation
^ and M-notation:
(Display control characters except for LFD(LineFeed or NewLine) and TAB using '^' notation and precede characters that have the high bit set with
'M-') M- notation is a way to display high-bit characters as low bit ones by preceding them with M-
You should read about little-endian and big-endian if you like to know more about M notation.
For example:
!http://i.imgur.com/0DGET5k.png?1
Check your manual page as below and it will list all options avaialable with your command and check is there -A present, if it is not present it is an illegal option.
man cat
It displays non-printing characters
In Mac OS you need to use -e flag and
-e Display non-printing characters (see the -v option), and display a dollar sign (`$') at the end of each line.

Can't read to var in Bash

I wrote a little Bash script and I'm having a problem while reading from the command line. I think its because I wrote the script on Windows. Here is the code:
read NEW_MODX_PROJECT
and the output of the debug mode
+ read $'NEW_MODX_PROJECT\r'
Finally here the error I get
': Ist kein gültiger Bezeichner.DX_PROJECT
I think in English it should mean "': is not a valid identifier.DX_PROJECT"
While writing it on Windows, it worked fine. I used console2 to test it which is using the sh.exe.
Your assertion is correct -- Windows uses CRLF line separators but Linux just uses a LF.
The reason for your strange error message is that while printing the name of your variable, it includes the carriage return as part of its name -- the terminal then jumps back to the first column to print the rest of the error message (which overwrites the beginning of the message with the end of it).
There are a set of utilities known as dos2unix and unix2dos which you can use to easily convert between formats, e.g.:
dos2unix myscript.sh
If you don't happen to have them, you can achieve the same using tr:
tr -d '\r' < myscript.sh > myscript-new.sh
Either will strip all the carriage returns and should un-confuse things.

backspace issue on linux file

I use EditPlus to write linux bash programs. after writting when i move files to server i get these kind of errors:
sleep: invalid time interval `2\r'
Try `sleep --help' for more information.
/usr/bin/program: line 9: $'\r': command not found
/usr/bin/program: line 10: $'}\r': command not found
/usr/bin/program: line 11: $'\r': command not found
/usr/bin/program: line 12: syntax error near unexpected token `$'{\r''
'usr/bin/program: line 12: `stop() {
I have also used dos2unix to fix this issue but no success. I want to know that is there any way that I can avoid this kind of problems. it waste alot of time. is there any better editor or some way to fix this issue?
EDIT:
What I do to solve this issue is that I vi a file in linux and then copy line by line from windows file to linux file and then it works. these are lines of my code:
line7:udevadm control --reload-rules
sleep 2
echo
echo $(date +"%b %e %T") hostname Program[$$]: Program Started | tee -a /var/log/messages
echo
}
stop() {
You need to change file preferences: go to Preferences -> Files and change "Create new file as " to UNIX. Also, your might want to enable "Check invalid CR/LF, null character when loading" option.
For already produced files
cat OLDFILE | tr -d '\r' > NEWFILE
should help. You can't just redirect the output to the input:
cat FILE | tr -d '\r' > FILE
since this will truncate the input file before it is read.
In contrast to similar programs, this is not eligible for the useless-use-of-cat award, since tr doesn't accept a filename as parameter.
Setting the "line ending sequence" in VSCode / atom from CRLF TO LF and saving worked for me

Resources