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.
I am just starting scripting and I have a question. I wonder if there is a shorter way of doing this.
I want to format the output from "id" command which looks like this:
uid=500(Administrator) gid=513(None) groups=0(root),513(None),544(Administrators),545(Users),1004(Debugger Users)
Now I want to fotmat it so that every of the 3 elements will be on its own line, ie.
I tried this:
id | tr -s " " "\n" (after every space put end-of-line character)
The result was that, (Debbuger Users) was cut into two pieces and this is exactly what I wanted to avoid.
thanks for your prompt reply. Please observe that there are three elements and the main component is the "=" sign. With this I mean
1)uid=500(Administrator)
2)gid=513(None)
3)groups=0(root),513(None),544(Administrators),545(Users),1004(Debugger Users)
Which means group=........(Debugger Users)also has to be one thing on one line.
What I tried was along way which I guess isn't a good solution especially when you have many outut lines from <id> command
So I went like this:
id | cut -d " " -f1 > file1 (cut first field and write to file1)
id | cut -d " " -f2 > file2(cut second field and write to file2)
cat file2 >> file(append file2 to file1)
then
id | cut -c 38-200(get the last field from character 38 to the end the write to file3)
I could see now it is working. I didn't type correctly sed 's/) /)\n/g', that's why I got wrong results. The solution ie perfect because it ignores the space (Debugger User) and only takes care of ) .
That comes with experience. Even now, after years and years of 'playing' with computers (I started in 1981 with a apple II Europlus), I still discover commands I haven't used/heard of before (seq is the last one I 'discovered').
Linux and unix have multiple ways of doing the same thing. Sometimes the chosen solution isn't to elegant or resource friendly but sometimes that isn't important (the work needs to be done).
And always try to 'see' other solutions that could make your work easier. For example: You initially focused on a space to solve the problem, I initially chose the equal sign. After looking at the string a bit longer I noticed the )<space> that could be used in an elegant way. Always take a little time to analyze the problem and work towards that what you know.
Another tip: Look at and try to understand (bash) scripts you come across, most of my knowledge comes from looking at and playing with scripts that where written by others.
How to quickly detemine what command(s) to use. I mean for me commands like tr, grep and sed 's///g' do almost the same thing.
Thanks.
My solution to this question has evolved into one answer: 'perl'. Many will argue that it is overkill for most problems, which is true. However, I never bump into the problem of not quite getting there with one tool or the other. Perl can be used for one-liner command-line solutions, as well as for full-blown applications, and all of the spectrum in between. Concepts that are central to the behavior of perl are mostly borrowed from other tools, and once you understand those concepts, you will find it easy to understand examples that are cited using the usual assortment of tools that you mentioned.
My $.02 worth.
--- rod.
EDIT:
BTW, the perl solution to this problem:
Code:
id | perl -e 'while(<>){ s/\) /\)\n/g; print $_;}'
How to quickly detemine what command(s) to use. I mean for me commands like tr, grep and sed 's///g' do almost the same thing.
Thanks.
Imagine this (Python):
Code:
>>> import os
>>> os.getlogin()
'root'
>>> os.getgid() #get real group id of current process
0
>>> os.getuid()
0
>>> os.getgroups() #return list of supplementary groups.
[0, 1, 2, 3, 4, 6, 10]
Also, no need to use regular expressions that much..
Code:
>>> fakeid="uid=500(Administrator) gid=513(None) groups=0(root),513(None),544(Administrators),545(Users),1004(Debugger Users)"
>>> for items in fakeid.split(" ",2): #stop at 2 space splits...
... print items
...
uid=500(Administrator)
gid=513(None)
groups=0(root),513(None),544(Administrators),545(Users),1004(Debugger Users)
Today I wanted to find the bigest file/directory . As a small exaple I used the current directory . So I went like this:
ls -l | sort -n -r -k 5 | head -n 1
(list me the files, sort them numerically with reference to the fifth column, reverse the sort to make it in discending order , after that cut the first line and that is what I wanted)
Again any suggestions on shorter ways? It seems I like to go too much around :-)
Today I wanted to find the bigest file/directory . As a small exaple I used the current directory . So I went like this:
ls -l | sort -n -r -k 5 | head -n 1
(list me the files, sort them numerically with reference to the fifth column, reverse the sort to make it in discending order , after that cut the first line and that is what I wanted)
Again any suggestions on shorter ways? It seems I like to go too much around :-)
I have a new problem. I have a simple game script. A user has to guess a randomly generated number, if he enters the same number as the one generated by the program, then the game is over. If he enters smaller number or bigger, he gets appropriate message.
My problem is: Users have to input only numbers, if they input anything other than a number, they should be informed of this. Now how should I check this?
Should I use:
if $input isnum? or test or maybe grep -v [0-9]?; but how?
---------------------------------------------------------------
Here is the script
------------------------------------------------
# A simple guessing script
# !/bin/bash
clear
times=0
randomnumber=$[$RANDOM * 40 / 32767]
try=0
echo "You have 10 tries "
echo
while [ $times -ne $randomnumber ]
do
echo -n "Please enter a number between 1 and 40 : "
read input
# here is where I wanted to enter the condition
#if [ isnum $input ]
#then
#echo "You can use only numbers "
try=$[$try+1]
if [ $try = 11 ]
then
echo " You have used all tries "
exit
else
if [ $input -eq $randomnumber ]
then
echo "Excellent "
exit
else
if [ $input -lt $randomnumber ]
then
echo "Too small "
else
echo "Too big "
fi
fi
fi
done
1) Use grep and the exit status to determine if it's a number:
Code:
#!/bin/bash
echo -n "Give number (1-40) : "
read input
echo $input | grep "[0-9][0-9]*" > /dev/null 2>&1
if [ "$?" -ne 0 ]
then
echo "Use a number please"
fi
If a command exits succesfull, the exit code will be 0 (zero). If it is not succesfull it will be something other then 0. The $? variable is special, it holds the exit code from the very last command executed.
So after the echo $input | grep....... the exit code is checked and if it is not 0 (zero) something other then a number is given.
2) Use bash internals, no need for external (i.e. grep in the previous example) command(s):
Code:
#!/bin/bash
typeset -i input
echo -n "Give number (1-40) : "
read input
if [[ $input == "0" ]]
then
echo "Use a number please"
fi
You (mis-)use bash' typeset -i input to declare input to be an integer. If anything else then a number is given, $input will be 0 (zero).
Downside: You cannot use 0 (zero). I.e: Give number (0-40). This is also the reason why I wrote (mis-)use
Personally I would choose solution number 2. I try to use bash internals as they are faster and there is no need for external commands.
Hmm, number from 1-40... "R2-D2" would pass your test! Try "^[1-9][0-9]*$" instead.
(Note: The ^ and $ are special chaaracters indicating the beginning and end of the line, so this guarantees that there is nothing but a number on the line. The [1-9] guarantees no leading zeros or minus signs. Then you can safely use numerical tests such as [ $input -le 40 ])
Bon voyage, Hockerbein
Oh, on the question of "how do you find the right command top do such-and-such" question, there are several search mechanisms:
A:- One is the command line "apropos keyword". (If that gives you nothing, as it just did on my brand new install, run the makewhatis indexing command first, /usr/sbin/makewhatis).
B:- Another is to browse man pages, specifically man something similar and go straight to the "SEE ALSO" section at the bottom of the man page.
On the scripting issue, I agree that perl has it all, however I'd consider there to be a heirarchy of languages for increasingly complicated code:
tr < sed < awk < perl
I dislike bash but it's useful I suppose. I write most of my scripts in either sed or awk. I sometimes use perl instead of sed on systems with a cruddy sed. E.g.:
sed 's?\(stuff\)ing?\1\1 <--- newline has to be typed literally on older systems
?g'
is equivalent to:
perl -p -e 's?(stuff)ing?$1$1\n?g' <-- newline is just \n
There are also new object oriented scripting languages such as Ruby and Python that have a great fan following, but I'm not convinced that they're anything to get excited about. But if you're keen, put them on your list of tricks to try out sometime.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.