How can I omit a specific comma from my output? - unix

I wanted to format my output using awk/sed, but I can't understand how to do it. I am using following command:
uptime | awk '{print $1" " $2" " $3$4" " $6" " $10$11$12}'
15:36:17 up 177days, 7 0.39,0.43,0.36
My desired output is
15:36:17 up 177days 7 0.39,0.43,0.36
I wanted to omit only first comma, i.e. the one after "177days".

Use either sub (substitute the comma with the empty string) or substr (make a substring with all but the last character):
uptime | awk '{sub(",","",$4); print $1" " $2" " $3$4" " $6" " $10$11$12}'
uptime | awk '{print $1" " $2" " $3 substr($4,1,length($4)-1) " " $6" " $10$11$12}'

Try piping the output of your command to a sed that'll match any alphabetic character followed by a comma and replace it with that character:
uptime | awk '{print $1" " $2" " $3$4" " $6" " $10$11$12}' | sed -r 's/(\w),/\1/'

Related

UNIX shell script reading csv

I have a csv file. I would like to put the fields into different variables. Supposed there are three fields in each line of the csv file. I have this code:
csvfile=test.csv
while read inline; do
var1=`echo $inline | awk -F',' '{print $1}'`
var2=`echo $inline | awk -F',' '{print $2}'`
var3=`echo $inline | awk -F',' '{print $3}'`
.
.
.
done < $csvfile
This code is good. However, if a field is coded with an embedded comma, then, it would not work. Any suggestion? For example:
how,are,you
I,"am, very",good
this,is,"a, line"
This may not be the perfect solution but it will work in your case.
[cloudera#quickstart Documents]$ cat cd.csv
a,b,c
d,"e,f",g
File content
csvfile=cd.csv
while read inline; do
var1=`echo $inline | awk -F'"' -v OFS='' '{ for (i=2; i<=NF; i+=2) gsub(",", "*", $i) }1' | awk -F',' '{print $1}' | sed 's/*/,/g'`
var2=`echo $inline | awk -F'"' -v OFS='' '{ for (i=2; i<=NF; i+=2) gsub(",", "*", $i) }1' | awk -F',' '{print $2}' | sed 's/*/,/g'`
var3=`echo $inline | awk -F'"' -v OFS='' '{ for (i=2; i<=NF; i+=2) gsub(",", "*", $i) }1' | awk -F',' '{print $3}' | sed 's/*/,/g'`
echo $var1 " " $var2 " " $var3
done< $csvfile
Output :
[cloudera#quickstart Documents]$ sh a.sh
a b c
d e,f g
So basically first we are trying to handle "," in data and then replacing the "," with "*" to get desired column using awk and then reverting * to "," again to get actual field value

Calculate length of string with only spaces in Unix for a fixed width file

I am having a fixed width file created via a BTEQ script in Unix. I am able to calculate the length correctly for all fields until the field which has some value.
In BTEQ script:
SELECT RPAD(COALESCE(SSO_ID,''),50,' ')||
RPAD(COALESCE(GENERIC4,''),100,' ')||
RPAD(COALESCE(GENERIC5,''),100,' ')||
RPAD(COALESCE(GENERIC6,''),100,' ')||
RPAD(COALESCE(GENERIC7,''),100,' ')||
RPAD(COALESCE(GENERIC8,''),100,' ')||
RPAD(COALESCE(GENERIC9,''),100,' ')||
RPAD(COALESCE(GENERIC10,''),100,' ')
FROM <view_name>
FILENM is an output file created via the above BTEQ script:
LENGTH_SSO_ID=`cat $FILENM | grep 57080249 |cut -c1361-1410| tr " " "~" | wc -c`
LENGTH_GENERIC4=`cat $FILENM | grep 57080249 |cut -c1711-1810| tr " " "~" | wc -c`
LENGTH_GENERIC5=`cat $FILENM | grep 57080249 cut -c1811-1910| tr " " "~" | wc -c`
LENGTH_GENERIC6=`cat $FILENM | grep 57080249 cut -c1911-2010| tr " " "~" | wc -c`
LENGTH_GENERIC7=`cat $FILENM | grep 57080249 cut -c2011-2110| tr " " "~" | wc -c`
LENGTH_GENERIC8=`cat $FILENM | grep 57080249 cut -c2111-2210| tr " " "~" | wc -c`
LENGTH_GENERIC9=`cat $FILENM | grep 57080249 |cut -c2211-2310| tr " " "~" | wc -c`
LENGTH_GENERIC10=`cat $FILENM | grep 57080249 |cut -c2311-2410| tr " " "~" | wc -c`
This is output I'm getting, where ideally I should get 100 length each for GENERIC columns.
LENGTH of SSO_ID=50
LENGTH of GENERIC4=5
LENGTH of GENERIC5=0
LENGTH of GENERIC6=0
LENGTH of GENERIC7=0
LENGTH of GENERIC8=0
LENGTH of GENERIC9=0
LENGTH of GENERIC10=0
Please advise why it is giving the incorrect length for columns which have spaces always and occur at the end of the record.

How to print additional string on every other line's contents in bash?

I'm using awk '{printf FILENAME ": "} NR%2==0' "$file", but it's printing the filename for each line. The desired behavior is for it to only print the filename next to even numbered lines.
Current output:
file1: file1: line2
file1: file1: line4
file1:
Desired output:
file1: line2
file1: line4
You are using printf(), so the right syntax is
$ cat file1.txt
line1
line2
line3
line4
$ awk ' NR%2==0 {printf("%s %s\n", FILENAME ": ", $0) } ' file1.txt
file1.txt: line2
file1.txt: line4
$
When you use
$ awk '{printf FILENAME ": "} NR%2==0' file1.txt
file1.txt: file1.txt: line2
file1.txt: file1.txt: line4
$
The printf prints file1.txt: and then for every even line number NR%2==0 evaluates to true, so it prints again file1.txt: line2
To know, what is happening just remove the NR%2==0,
$ awk '{printf FILENAME ": "} ' file1.txt
file1.txt: file1.txt: file1.txt: file1.txt:
$
so, printf just prints the filename without new lines. The right usage of printf() is like C syntax - specify format specifier %s for string, %d for Int, etc followed by the variable.
ex printf("%d %s\n", NR, $0 )
$ awk ' { printf("%d %s\n", NR, $0 ) }' file1.txt
1 line1
2 line2
3 line3
4 line4
$
Note that there is difference between where you place the condition
awk ' NR%2==0 {printf("%s %s\n", FILENAME ": ", $0) } ' file1.txt
is different from
awk ' {printf("%s %s\n", FILENAME ": ", $0) } NR%2==0 ' file1.txt
Both give different results
The first one checks the condition and then prints - so you get only 2 lines.
The second prints all lines by default and when "NR%2==0" is true, the $0 is printed again - you get 6 lines ( 4 original + 2 for the true condition )
Hope this helps.
Could you please try following.
awk 'FNR%2==0{print FILENAME": " $0}' Input_file
OR as per OP's try in case you are passing a variable in pace of Input_file
awk 'FNR%2==0{print FILENAME": " $0}' "$file"
To avoid too many open files error try following once.
awk 'prev!=FILENAME{close(prev)} FNR%2==0{print FILENAME": " $0} FNR==1{prev=FILENAME}' "$file"

I need list of files in long format that contain string

I want to have the list of files, in long format (ls -l) including date and time, that contain an specific string and if possible, number of occurrences.
The most I have achieved is a list of files (just the name) with number of occurrences:
grep -c 'string' * | grep -v :0
That shows something like:
filename:number of occurrences
But I cannot improve it to show also file date and time. It has to be something simple, but I am a bit newbie.
I have used -s for ignoring the folder warnings. ':0$' is the regex for ending in :0. awk then calls ls -l on just the filenames found, then | tr '\n' ' ' replaces the newlines of the ls command with spaces. We output the number of occurences at the end of each line so we don't lose the info while going forward. The last awk is to just to print the columns needed.
grep -c 'form-group' * -s | grep -v ':0$' | awk -F ':' '{ printf system( "ls -l \"" $2 "\" | tr \"\n\" \" \"" ); print " " $3 }' | awk -F ' ' '{ print $6 " " $7 " " $8 " " $9 " : " $11 }'
Here is some sample output:
Sep 1 13:47 xxx.blade.php : 12
Sep 1 13:47 xxx.blade.php : 5
Sep 1 13:47 xxx.blade.php : 6
Sep 11 17:25 xxx.blade.php : 4
Sep 4 15:03 xxx.blade.php : 6

sub and gsub function?

I have this command:
$ find $PWD -name "*.jpg" | awk '{system( "echo " $(sub(/\//, "_")) ) }'
_home/mol/Pulpit/test/1.jpg
Now the same thing, but using gsub:
$ find $PWD -name "*.jpg" | awk '{system( "echo " $(gsub(/\//, "_")) ) }'
mol#mol:~
I want to get the result:
_home_mol_Pulpit_test_1.jpg
Thank you for your help.
EDIT:
I put 'echo' to test the command:
$ find $PWD -name "*.jpg" | awk '{gsub("/", "_")} {system( "echo " mv $0 " " $0) }'
_home_mol_Pulpit_test_1.jpg _home_pic_Pulpit_test_1.jpg
mol#mol:~
I want to get the result:
$ find $PWD -name "*.jpg" | awk '{gsub("/", "_")} {system( "echo " mv $0 " " $0) }'
/home/pic/Pulpit/test/1.jpg _home_pic_Pulpit_test_1.jpg
That won't work if the string contains more than one match... try this:
echo "/x/y/z/x" | awk '{ gsub("/", "_") ; system( "echo " $0) }'
or better (if the echo isn't a placeholder for something else):
echo "/x/y/z/x" | awk '{ gsub("/", "_") ; print $0 }'
In your case you want to make a copy of the value before changing it:
echo "/x/y/z/x" | awk '{ c=$0; gsub("/", "_", c) ; system( "echo " $0 " " c )}'

Resources