Linux - SoftwareThis forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.
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.
Distribution: Red Hat 7.2/8/9, Fedora Core 1/2/3, Smoothwall, Mandrake 7.0/10, Vecter 4, Arch 0.6, EnGuarde
Posts: 289
Rep:
sed & grep script?
I don't know if I am doing the right thing or the wrong thing here. I'm uncertain.
I have a program that reports information into a log file ever 3 seconds. When a player joins the server, it reports it. When the player leaves the server, it reports it.
I'm creating a script that uses grep to take the lines with the players joining and leaving and isolate them into a tempary storage place.
I then use sed to make the isolated information, awk usable.
But the problem is, I can not figure out how to get my script to find matchs from peices of those who joined, and peices of those who left and request a delete of both.
This is important because my objective is to setup the program to display "only" the players that are "currently" in the game.
If someone can give me a hint, idea, or even help me with this, I would be most greatful.
This is what my log file looks like after my script works with it:
Distribution: Red Hat 7.2/8/9, Fedora Core 1/2/3, Smoothwall, Mandrake 7.0/10, Vecter 4, Arch 0.6, EnGuarde
Posts: 289
Original Poster
Rep:
I thought about doing something this:
sed 's/"$(grep OFF filename)//g' filename > filename2
Problem with this is, it will only delete those flagged with OFF and not touch ON. I want those flagged with OFF to delete the same ones with ON then delete the ones with OFF. Man, my mind is exploading lol
Distribution: Red Hat 7.2/8/9, Fedora Core 1/2/3, Smoothwall, Mandrake 7.0/10, Vecter 4, Arch 0.6, EnGuarde
Posts: 289
Original Poster
Rep:
Okay, I tried this out...
# Buffer.mem is full log of all ON and OFF players
grep OFF buffer.mem > test.mem
sed 's/OFF//g' test.mem > test2.mem
sed 's/[[]//g' test2.mem > test.mem
sed 's/...................]//g' test.mem > test2.mem
grep ON buffer.mem > p.mem
sed 's/ON//g' p.mem > p2.mem
sed 's/[[]//g' p2.mem > p.mem
sed 's/...................]//g' p.mem > p2.mem
sed 's/$(grep * test2.mem)//g' p2.mem > p3.mem
All it did was say I had new mail and copied everything from p2.mem into p3.mem.
If your only aim is to find out what users are online at a given moment, I think you can do it 'on the fly', with one line of code, and without any temporary files.
You shall only check what was the last action (ON or OFF) of each user.
If it was ON, the user is online.
This line does the trick:
tac logfile | sort | uniq | awk '{printf $2 " " $1 "\n"}' | uniq -f 1 | grep ON | awk '{printf $1 "\n"}'
The input of the above command shall be in logfile, and each line should look like this:
user action
(There should be no spaces in either user or in action)
So, the above line needs some tweaking, but I think it can do the task.
grep Joined $LOGFILE > $BUFFER
grep Left $LOGFILE >> $BUFFER
sed 's/] /]~/g' $BUFFER > $BUFFER2
sed 's/ (........) Joined as Player [0-9]/~ON~/g' $BUFFER2 > $BUFFER
sed 's/ (........) Joined as Player [0-9][0-9]/~ON~/g' $BUFFER > $BUFFER2
sed 's/ Left as a Player (..............)/~OFF~/g' $BUFFER2 > $BUFFER
sed 's/ Left as a Player (...............)/~OFF~/g' $BUFFER > $BUFFER2
sed 's/[.]//g' $BUFFER2 > $LOG
Well, in the meantime I also noticed the script only gives correct results in specific cases, which I tried :-( .
I also found what the problem is: the first 'sort' pipe sorts the lines on the whole line, and not on the 'user' field only.
If we could establish that 'sort' only sorts the lines on the 'user' field (and othervise leave the lines in the positional order), then the whole thing would work.
If you issue the 'sort' command like this: sort +1, then sort will sort on the second field (e.g. username).
The problem is that even if you specify on which field to sort, 'sort' will also sort on other fields, not leaving the lines in the positional order.
This is the last problem to solve for the script to work.
#! /bin/bash
# Location of the file shown in your first post
ALLONOFF="/PATH/TO/ON-OFF-ENTRIES"
# Need sed to strip (multiple) spaces in username
for THIS_USER in `cat ${ALLONOFF} | sed 's/ [ ]*//g' | awk -F~ '{ print $2 }' | sort | uniq`
do
NO_ONLINE="`cat ${ALLONOFF} | sed 's/ [ ]*//g' | grep ${THIS_USER} | grep -c '~ON'`"
NO_OFFLINE="`cat ${ALLONOFF} | sed 's/ [ ]*//g' | grep ${THIS_USER} | grep -c '~OFF'`"
if (( ${NO_ONLINE} != ${NO_OFFLINE} && ${NO_ONLINE} > ${NO_OFFLINE} ))
then
echo "${THIS_USER} : Still on-line."
fi
done
My startingpoint for this problem:
If the amount off ON's equals the amount of OFF's for a specific user he/she must be off-line.
In theory there can be more OFF's then ON's for a specific, which would give you a false hit. That's why the && ${NO_ONLINE} > ${NO_OFFLINE} part is included.
I don't know if you have a correct output of the file you show in your first post, but this is the result after feeding that info into the above script:
CH47Wind : Still on-line.
CloudZero : Still on-line.
Crazlatinboy77 : Still on-line.
Gimzur : Still on-line.
JamesDarren : Still on-line.
Nicky510 : Still on-line.
PhanserAdoze : Still on-line.
RaY_EX : Still on-line.
Rushby : Still on-line.
SKULLEY : Still on-line.
SPIRIT_WIND_ : Still on-line.
Sneb730 : Still on-line.
Souldealer : Still on-line.
TheDirtyAzn : Still on-line.
UlrichVonVentura : Still on-line.
ZePlAr-RaIdErZ : Still on-line.
_OmegaNemisis_ : Still on-line.
justinhoskins : Still on-line.
killer696 : Still on-line.
klackdink : Still on-line.
roninmetu : Still on-line.
rsherroc : Still on-line.
tcjg2 : Still on-line.
vendomslayer : Still on-line.
You might prefer to return the results on one line separated by ',' , this can do it:
tac logfile | awk '{ printf $2 " " $1 "\n" }' | sort -s +1 | uniq | uniq -f 1 | grep ON | awk '{ printf $2 ", " }'
(though you may want to remove the last trailing ', ' after the line is built)
Your original idea of counting ON and OFF actions is OK, I simply prefer doing everything with sed, awk, sort and grep, as I am fascinated with the power and speed of these commands.
If you follow your original idea, you inevitably need a script to cycle through each username and count their actions.
My idea may provide you the easiness of trying and tweaking it on the command line, then append it to your script when it works.
I saw the possibility that the last action of each user could be easily found by some sorting and if it was an ON action, then the user is online.
So, here is the final, complete solution for analyzing the player.log file in a previous post of yours:
tac player.log | sed 's/ /%+/g' | sed 's/~/ /g' | awk '{ printf $3 " " $2 "\n" }' | sort -s +1 | uniq | uniq -f 1 | grep ON | awk '{ printf $2 ", " }' | sed 's/%+/ /g' | sed 's/, $//'
The above line produces the following output when feeding your example lines to it: cao200
Since uniq does not seem to handle field delimiters other than space, I replaced spaces in usernames with a string '%+' (which I replace back to space in the last step), and I also replace the '~' field delimiter to space.
This was done with three additional sed commands.
If there are more than one user online, then the script outputs them on one line, using ', ' as the separator. So, the output of the script is a string, in which all users online are listed.
The last sed command removes the unnecessary, trailing ', ' characters from the end of the output line.
The one-liner works for the short example, but an error occurs when feeding it the longlist shown in the first post.
Error:
awk: cmd. line:1: (FILENAME=- FNR=15) fatal: not enough arguments to satisfy format string
`ON Bel%+Lord%+of%+the%+First
'
^ ran out for this one
printf is the culprint. Change the following and it will work:
Distribution: Red Hat 7.2/8/9, Fedora Core 1/2/3, Smoothwall, Mandrake 7.0/10, Vecter 4, Arch 0.6, EnGuarde
Posts: 289
Original Poster
Rep:
I been working on it since this morning. I'm going to take a break, then try your idea's out. Again, I'll report the feed back and thanks for the efforts.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.