How to assign variables in a csh script and used them as arguments for that same script? - unix

Good day,
Hoping for the kind help of anyone here, thanks in advance.
I have T.csh which looks like this:
#! /bin/csh
set a="01 02 03 04 05 06 07 08 09 10 11 12 13"
set b="14 15 16 17 18 19 20 21 22 23 24 25"
set c="01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25"
set X = `grep $1 EOL.txt | head -n1 | cut -d- -f1`
printf "$X\n$2\n$3\nYYYY\n1\nN\n"
The variables a,b and c are optionally used as the 3rd argument in the printf line. The problem is, whenever I try to run the script, it showed undefined variable. These set command lines are working whenever I assigned them interactively, but inside the script, it seems to not work. Perhaps I need to initialize it but could not figure out how. Just new to this programming thing, I hope someone here can help me. Thanks a lot in advance.
Here are the sample execution and error for your reference:
CAT-46{bc2}40>set a="01 02 03 04 05 06 07 08 09 10 11 12 13"
CAT-46{bc2}41>./T.csh 4773 XXXX.XX "$a"
62
XXXX.XX
01 02 03 04 05 06 07 08 09 10 11 12 13
82869
1
N
CAT-46{bc2}42>unset a
CAT-46{bc2}43>./T.csh 4773 XXXX.XX "$a"
a: Undefined variable
CAT-46{bc2}44>
If i set the variables manually,it's OK, but when I called for it from the script, its flagging undefined variable error.
Mike

I post another answer because a comment is too short. Look at the following.
I have a script named /tmp/T.csh:
#!/bin/csh
set a="blah"
echo $a
My shell is bash; I type /tmp/T.csh: result is blah (csh executed the script).
Still in bash; I type unset a; /tmp/T.csh $a: result is the same.
Still in bash; I type . /tmp/T.csh: no result (bash executed the script).
I type csh; now I am in csh.
I type /tmp/T.csh: result is blah (of course).
I type /tmp/T.csh $a: "a: Undefined variable"
set a = something
/tmp/T.csh $a: blah
echo $a: something
unset a
echo $a: "a: Undefined variable"
I replicated all you did; hope this helps.
You get an error for what you wrote on the command line, not for the content of your script. Even a simple echo, as you can see here above, gives an error if you on the command line refer to a variable which does not exist.

prompt> unset a
prompt> ./T.csh 4773 XXXX.XX "$a"
The first command, "unset a", deletes the variable. In the second command you try to read the variable (on the command line!). That is why csh complains.

Related

How to Extract logs between 2 timestamps in Unix

I need to extract the logs between two timestamps from a file in Unix. I basically kind of need those logs to be copied and output in a different file so that I can copy them.
Is there an efficient way to do this? The log format looks like this - The timestamp is in a separate line from the actual logs.
Tue 21 Apr 14:00:00 GMT 2020
{"items":[{"cpu.load": "0.94","total.memory": "6039.798 MB","free.memory": "4367.152 MB","used.memory": "1672.646 MB","total.physical.system.memory": "16.656 GB","total.free.physical.system.memory": "3860.197 MB","total.used.physical.system.memory": "12.796 GB","number.of.cpus": "8"}]}
Tue 21 Apr 18:00:00 GMT 2020
{"items":[{"cpu.load": "0.76","total.memory": "6039.798 MB","free.memory": "4352.656 MB","used.memory": "1687.142 MB","total.physical.system.memory": "16.656 GB","total.free.physical.system.memory": "3858.203 MB","total.used.physical.system.memory": "12.798 GB","number.of.cpus": "8"}]}
I am doing this but it only prints out the timestamp and not the actual logs
cat file.txt | awk -F, '{ if ($1>"Fri 21 Aug 14:00:00 GMT 2020" && $1<"Sat 22 Aug 18:00:00 GMT 2020") print }'
Can someone advice.

Kornshell - How to print a file starting from a certain string to the end of the file?

I am currently using KSH.
There is a file with text in it, and say we're looking for a certain string inside that text.
How would you print the contents of that file starting from that certain string to the end of file?
I know that,
sed '/\(pattern\).*/{s//\1/; q;}'
will print the file starting from the beginning up until the string is found. I tried swapping it and I guess that does not work.
Thank you,
Vincent
Through sed,
sed -n '/pattern/,/&/p' file
If you want to print all the text which are next to the pattern then follow the below example,
$ cat ccc
foo
blah bar blah
gjhj
jjhk
$ sed -n '/ bar /,/&/p' ccc | sed -r 's/^.* (bar.*)$/\1/g'
bar blah
gjhj
jjhk
And through awk,
$ awk '/ bar / {sub (/^.*bar/,"bar"); f=1} f' ccc
bar blah
gjhj
jjhk
I think you want this command,
$ cal 6 2014 | awk 'NR==1{print} NR==2{print} / 20 / {sub (/^.*20/,"20"); f=1} f'
June 2014
Su Mo Tu We Th Fr Sa
20 21
22 23 24 25 26 27 28
29 30
If you want to properly arrange the date and day then try this,
$ cal 6 2014 | awk 'NR==1{print} NR==2{print} / 20 / {sub (/^.*20/," 20"); f=1} f'
June 2014
Su Mo Tu We Th Fr Sa
20 21
22 23 24 25 26 27 28
29 30
You could use awk
awk '/pattern/ {f=1} f' file
When pattern is found, set flag f to true.
If flag f is true, print the line.
I do prefer this version compare to the range version, since its more flexible if you have other test to do to.
Another awk using range.
awk '/pattern/,0' file
Here the end pattern never becomes true, so it does not stop printing after start pattern is found.
Using range with sed
sed -n '/pattern/,$p' file
Print from pattern and rest of line. My pattern is yo
cat file
Here is my data
What do you like
I like ice creem
awk -F "yo" 'NF>1 {f=1;print FS$2;next} f' file
you like
I like ice creem

Unix grep line above and concatenate

here is my sample input from a log file.
#2014 03 06 11:21:44:028#+1300#
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[UserID= testUser]
What I am trying to do is go through all the log entries and do a grep command on the "UserID=" and then get the line 2 lines above (the timestamp). I then wish my output file to be a concatenation of the two into the file tempLog.txt
#2014 03 06 11:21:44:028#+1300# [UserID= testUser]
Can anyone help me with this? Still kinda new to Unix.... :)
Thanks
Chris
UPDATED DUMMY DATA
#2.#2014 03 06 11:21:29:163#+1300#Info#/System/Security/Audit/Logon#
#xxxxxx (Has white spaces)
Logon failed | LOGIN.ERROR | null | | Login Method=[default], IP Address=[xx.xx.xxxx], UserID=[testUser], Reason=[Authentication did not succeed.]#
give this line a try:
grep --group-separator="" -B2 'UserID=' file|awk -v RS="" -F '\n' '{$2=""}7'
test:
kent$ cat f
fooba
#2014 03 06 11:21:44:028#+1300#
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[UserID= testUser]
foo
bar
#2014 03 06 11:21:44:028#+1400#
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[UserID= testUser2]
kent$ grep --group-separator="" -B2 'UserID=' f|awk -v RS="" -F '\n' '{$2=""}7'
#2014 03 06 11:21:44:028#+1300# [UserID= testUser]
#2014 03 06 11:21:44:028#+1400# [UserID= testUser2]
This awk should do:
awk '/#20/ {f=$0} /\[UserID/ {print f,$0}' file
#2014 03 06 11:21:44:028#+1300# [UserID= testUser]

List only hex value named files

Using QNX, i'm creating a script that will list only hex valued files under 1F.
/path# ls
. 05 09 0B pubsub09
.. 07 09_sub 0E
04 08 0A 81
/path#
I have code that should list only hex values, but it still lists the whole directory.
ls /path/ |
while read fname
do
if [ "ibase=16; $fname" ]
then
echo "$fname"
fi
done
return 0
Try this instead
if [[ $fname =~ ^[[:xdigit:]]+$ ]]

extract a string after a pattern

I want to extract the numbers following client_id and id and pair up client_id and id in each line.
For example, for the following lines of log,
User(client_id:03)) results:[RelatedUser(id:204, weight:10),_RelatedUser(id:491,_weight:10),_RelatedUser(id:29, weight: 20)
User(client_id:04)) results:[RelatedUser(id:209, weight:10),_RelatedUser(id:301,_weight:10)
User(client_id:05)) results:[RelatedUser(id:20, weight: 10)
I want to output
03 204
03 491
03 29
04 209
04 301
05 20
I know I need to use sed or awk. But I do not know exactly how.
Thanks
This may work for you:
awk -F "[):,]" '{ for (i=2; i<=NF; i++) if ($i ~ /id/) print $2, $(i+1) }' file
Results:
03 204
03 491
03 29
04 209
04 301
05 20
Here's a awk script that works (I put it on multiple lines and made it a bit more verbose so you can see what's going on):
#!/bin/bash
awk 'BEGIN{FS="[\(\):,]"}
/client_id/ {
cid="no_client_id"
for (i=1; i<NF; i++) {
if ($i == "client_id") {
cid = $(i+1)
} else if ($i == "id") {
id = $(i+1);
print cid OFS id;
}
}
}' input_file_name
Output:
03 204
03 491
03 29
04 209
04 301
05 20
Explanation:
awk 'BEGIN{FS="[\(\):,]"}: invoke awk, use ( ) : and , as delimiters to separate your fields
/client_id/ {: Only do the following for the lines that contain client_id:
for (i=1; i<NF; i++) {: iterate through the fields on each line one field at a time
if ($i == "client_id") { cid = $(i+1) }: if the field we are currently on is client_id, then its value is the next field in order.
else if ($i == "id") { id = $(i+1); print cid OFS id;}: otherwise if the field we are currently on is id, then print the client_id : id pair onto stdout
input_file_name: supply the name of your input file as first argument to the awk script.
This might work for you (GNU sed):
sed -r '/.*(\(client_id:([0-9]+))[^(]*\(id:([0-9]+)/!d;s//\2 \3\n\1/;P;D' file
/.*(\(client_id:([0-9]+))[^(]*\(id:([0-9]+)/!d if the line doesn't have the intended strings delete it.
s//\2 \3\n\1/ re-arrange the line by copying the client_id and moving the first id ahead thus reducing the line for successive iterations.
P print upto the introduced newline.
D delete upto the introduced newline.
I would prefer awk for this, but if you were wondering how to do this with sed, here's one way that works with GNU sed.
parse.sed
/client_id/ {
:a
s/(client_id:([0-9]+))[^(]+\(id:([0-9]+)([^\n]+)(.*)/\1 \4\5\n\2 \3/
ta
s/^[^\n]+\n//
}
Run it like this:
sed -rf parse.sed infile
Or as a one-liner:
<infile sed '/client_id/ { :a; s/(client_id:([0-9]+))[^(]+\(id:([0-9]+)([^\n]+)(.*)/\1 \4\5\n\2 \3/; ta; s/^[^\n]+\n//; }'
Output:
03 204
03 491
03 29
04 209
04 301
05 20
Explanation:
The idea is to repeatedly match client_id:([0-9]+) and id:([0-9]+) pairs and put them at the end of pattern space. On each pass the id:([0-9]+) is removed.
The final replace removes left-overs from the loop.

Resources