unix ksh how to print $1 and first n characters of $2

Viewed 109

I have a file as follows:

$ cat /etc/oratab  
hostname01:DBNAME11:/oracle_home/A_19.0.0.0:N
hostname01:DBNAME1_DC:/oracle_home/A_19.0.0.0:N
hostname02:DBNAME21:/oracle_home/B_19.0.0.0:N
hostname02:DBNAME2_DC:/oracle_home/B_19.0.0.0:N

I want print the unique of the first column, first 6 characters of the second column and the third column when the third column matches the string "19.0.0".

The output I want to see is:

hostname01:DBNAME1:/oracle_home/A_19.0.0.0
hostname02:DBNAME2:/oracle_home/B_19.0.0.0

I put together this piece of code but looks like its not the correct way to do it.

cat /etc/oratab|grep "19.0.0"|awk '{print $1}' || awk -F":" '{print subsrt($2,1,8)}

sorry I am very new to shell scripting

4 Answers

1st solution: With your shown sample please try following, written and tested with GNU awk.

awk 'BEGIN{FS=OFS=":"} {$2=substr($2,1,7)} !arr[$1,$2]++ && $3~/19\.0\.0/{NF--;print}' Input_file


2nd solution: OR in case your awk doesn't support NF-- then try following.

awk '
BEGIN{
  FS=OFS=":"
}
{
  $2=substr($2,1,7)
}
!arr[$1,$2]++ && $3~/19\.0\.0/{
  $4=""
  sub(/:$/,"")
  print
}
' Input_file

Explanation: Simple explanation would be, set field separator and output field separator as :. Then in main program, set 2nd field to 1st 7 characters of its value. Then check condition if they are unique(didn't occur before) and 3rd field is like 19.0.0, reduce 1 field and print that line.

You may try this awk:

awk 'BEGIN{FS=OFS=":"} $3 ~ /19\.0\.0/ && !seen[$1]++ {
print $1, substr($2,1,7), $3}' /etc/fstab

hostname01:DBNAME1:/oracle_home/A_19.0.0.0
hostname02:DBNAME2:/oracle_home/B_19.0.0.0

We check and populate associative array seen only if we find 19.0.0 in $3.

If the lines can be like this and ending on 19.0.0

hostname01:DBNAME1:/oracle_home/A_19.0.0.0
hostname01:DBNAME1:/oracle_home/A_19.0.0.1

and the hostname01 only should be unique, you might miss a line.


You could match the pattern using sed and use 2 capture groups that you want to keep and match what you don't want.

Then pipe the output to uniq to get all unique lines instead of line the first column.

sed -nE 's/^([^:]+:.{7})[^:]*(:[^:]*19\.0\.0[^:]*).*/\1\2/p' file | uniq

Output

hostname01:DBNAME1:/oracle_home/A_19.0.0.0
hostname02:DBNAME2:/oracle_home/B_19.0.0.0
$ awk 'BEGIN{FS=OFS=":"} index($3,"19.0.0"){print $1, substr($2,1,7), $3}' file | sort -u
hostname01:DBNAME1:/oracle_home/A_19.0.0.0
hostname02:DBNAME2:/oracle_home/B_19.0.0.0
Related