ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
OK, I didn't know wherelse to ask this one. I have a script that I've made which takes two arguments: a pure number and a filename.
I decided to give it a little bit of flexibility and have it so that it doesn't matter what order those two arguments are put: number then file name, or file name then number. Doesn't matter.
Well, all well and good. But I need to be able to take a word ($1 or $2 in this case) and figure out if it only contains numbers, if not do a
Code:
echo "You complete moron! What'd you take me for!" > /dev/stderr
(or something to that effect).
OK, so my first idea is this (kinda of weird I know):
Code:
if [ $1 = "$(echo $1 | awk '{print strtonum($0)}')" ]; then
echo "Numeric only value! Good job!"
else
echo "You fruitcake! Where do you think you get off! Huh?"
fi
The idea is that since the awk function "strtonum()" will return only numeric values, compare what it returns of the argument to what the entire argument is. If they match, then of course they had only typed in numeric values.
Two issues: the awk function strtonum() will believe that the string is a hexidecimal number if proceeded by a 0x. also, if it starts with a 0, then it is interpreted as an octal number. That might be a problem in the unlikely circumstance that somebody would do that. And again, if my little script became so popular that the world over uses it, some Linux newbie in the worlde will burst out in tears as his script just simply doesn't work for some hidden reason only the original programmer (me, in this case) would possibly know about. And as he asks the question over and over again "why? why? why?", the answer shall remain hidden in the way that strtonum() impliments its magic!
Or, in other words: is there a better way? Is there a more common way? Anybody tried this before?
Thanks for the quick response! I'll try 'er out as soon as I can. Your way looks a little bit better. I think it's a better approach: you don't really analyze the text a whole lot. Kinda kool!
I am not very happy with it though (printf error redirected to /dev/null),
maybe this is better :
Code:
function is_integer() {
s=$(echo $1 | tr -d 0-9)
if [ -z "$s" ]; then
return 0
else
return 1
fi
}
if is_integer $1; then
echo "$1 is an integer"
else
echo "$1 is not an integer"
fi
I use this to separate the text from the numerics in a bash script.
# In this example a file name is one of the expected inputs, a number the other.
Code:
for itm in "$@"
do
if [ -f "$itm" ]
then
afile="$itm"
else
cnt=`echo "$itm" | sed -e /\[0-9\]/!d -e /\[\.\,\:\]/d -e /\[a-zA-Z\]/d`
if [ -z "$cnt" ]
then
cnt=0
fi
fi
done
# what is accomplished by the script
1. Tests for a file name, sets a variable to that file name.
2. Tests for a number, sets a variable to that number.
The sed line:
- confirms an integer number exists in the text and keeps the text
- drops decimal numbers or text having a period
- drops text having a comma or colon
- drops text having alphas
The $cnt variable is tested for null and assigned the value 0 if null.
I am using integers greater than zero, which is why I set $cnt to zero if no integer numbers were found as a result of the string returned by sed. I test $cnt for zero elsewhere in the rest of my script.
I use the file name and numeric variables elsewhere in a custom script.
I was intrigued by finding a better solution than my lightweight version, and so created a script that runs a series of tests to validate data. The types checked are file, integer decimal, comma delimited integer, comma delimited decimal. After burning through some serious kludge versions, I arrived at some positive results. See what you think.
Code:
#!/bin/sh
#
# fx
#
# A test script to validate input data.
# A variable list is substituted for manual input.
# Note: before running this script try ls > tx for a test file. See below args.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# spaces for output padding
sp=' '
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# try a test sample of arguments to observe the classification results
for arg in 1234 1,222,333,444 12345.00591 1,222,333,444.555789 tx abc 5,00 6,00.007 123abc def456 ',.' ',500' 'a.txt' 127.1.1.1
do
# try various tests with direct string susbstitution or sed for complex tasks
#
# the first 3 tests are for the simple: file, integer, decimal (no comma numbers)
if [[ -f $arg ]];then
stat=file
elif [[ $arg == ${arg//[^0-9]/} ]];then
stat=integer
elif [[ `echo $arg | sed '/^[0-9]\{1,24\}\.[0-9]\{1,24\}$/!d'` ]];then
stat=decimal
else
# The more complex comma integer and decimal numbers are handled here.
# Any other data falls thru as unqualified.
# ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~
if [[ $arg == ${arg//[^0-9,]/} ]];then
# proof for comma placement
if [[ `echo $arg | sed 's/^[0-9]\{1,3\},//;/\([0-9],\)\{1,8\}/!d'` ]];then
stat=comma_integer
else
stat=unqualified
fi
elif [[ $arg == ${arg//[^0-9,\.]/} ]];then
# proof for comma placement
if [[ `echo $arg | sed 's/^[0-9]\{1,3\},//;s/\(\.[0-9]\{1,24\}\)//;/\([0-9],\)\{1,8\}/!d'` ]];then
stat=comma_decimal
else
stat=unqualified
fi
else
# fallthru for non: file, integer, decimal, int-comma, dec-comma
stat=unqualified
fi
# ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~
fi
# # # # # # # # # # # # # # # # # # # # # #
# create a column offset for results
#
let "lng=24-${#arg}"
pad=${sp:0:$lng}
echo "Status of ( $arg ): $pad $stat"
# # # # # # # # # # # # # # # # # # # # # #
done
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# EOF
#
Hello, your welcome. Hope the code is interesting/of use.
Actually this is correct: [[ $arg == ${arg//[^0-9]/} ]]
The statement is substituting nothing for any characters that are not 0-9, so that integer numbers only will pass through the substitution unchanged, and this will make the terms equal in characters and test bracket test condition passes; but any non numerics will be substituted out of the right side argument, which makes the bracket test condition fail.
Note that nothing follows the farthest right slash, which is what is substituted.
The double slash indicates to substitute all matching characters specified in the test.
Quick example:
Input: 1500 Test Output: 1500 Input == Output Pass
Input: 8.25 Test Output: 825 Input != Output Fail
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.