user5354933
user5354933

Reputation:

awk - printing x amount of characters based on string length

So I'm trying to read some config files and output the information from find piped into grep over to awk as follows:

find /path/to/file/ -name config.php -print0 | xargs -0 grep -E 'cfg_database|cfg_user|cfg_password' | awk -F"[:']" -v OFS="" '{print (NR%3==1) ? $1 " | Database: " : "", (NR%3==2) ? "Username: " : "", (NR%3==0) ? "Password: " : "", $5}'

There would be multiple results so by default, find | xargs grep output is:

/path/to/file/dir1/config.php:define('cfg_database', 'db1');
/path/to/file/dir1/config.php:define('cfg_user', 'user1');
/path/to/file/dir1/config.php:define('cfg_password', 'pass1');
/path/to/file/dir2/config.php:define('cfg_database', 'db2');
/path/to/file/dir2/config.php:define('cfg_user', 'user2');
/path/to/file/dir2/config.php:define('cfg_password', 'pass2');

With the command I have right now, the output is:

/path/to/file/dir1/config.php | Database: db1
Username: user1
Password: pass1

But I want to be able to prepend spaces so that all of the results are lined up based on the length of path to the file ($1) plus three more spaces.

/path/to/file/dir1/config.php | Database: db1
                                Username: user1
                                Password: pass1

The only methods I'm seeing here are using a loop within print for length($1), or using printf. I couldn't figure out any ways of getting the loop in the current command, and I don't know much about printf and couldn't figure out a way of determining what line is being read. Either way, would appreciate someone pointing me in the right direction.

Upvotes: 1

Views: 4550

Answers (3)

James Brown
James Brown

Reputation: 37394

$ awk 'NR==1{s=length($1)+4}NR>1{$s=$1 OFS $2;$1=$2=""}1' file

or

$ awk '
NR==1 {
    s=length($1)+4   # length of first field of first record + correction
}
NR>1 {
    $s=$1 OFS $2     # use length to position to correct field
    $1=$2=""         # clean original fields
}1' file
/path/to/file/dir1/config.php | Database: db1
                                Username: user1
                                Password: pass1

Upvotes: 0

Akshay Hegde
Akshay Hegde

Reputation: 16997

your_command | awk 'FNR==1{l=index($0,"|")+1}FNR>1{$0=sprintf("%*s%s",l,"",$0)}1'

For example :

$ cat f
/path/to/file/dir1/config.php | Database: db1
Username: user1
Password: pass1

$ awk 'FNR==1{l=index($0,"|")+1}FNR>1{$0=sprintf("%*s%s",l,"",$0)}1' f
/path/to/file/dir1/config.php | Database: db1
                                Username: user1
                                Password: pass1

Explanation

  • index(str, sub)

It checks whether sub is a substring of str or not. On success, it returns the position where sub starts; otherwise it returns 0. The first character of str is at position 1.

  • sprintf(format, expression1, …)

Return (without printing) the string that printf would have printed out with the same arguments

  • sprintf("%*s%s",l,"",$0)

Like C/C++ Specifies how much space to allocate for the string

* The width is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.

sprintf("%*s",5,"")

is same as

sprintf("%5s", "");   

Example

Used to specify, in a dynamic way, what the width of the field is:

$ awk 'BEGIN{printf("%*s%s\n",5,"","mystring")}'
     mystring

$ awk 'BEGIN{printf("%5s%s\n","","mystring")}'
     mystring

Upvotes: 4

P....
P....

Reputation: 18351

awk 'NR==1{len=length($0)} {printf "%"len"s\n",$0}' yourfile
/path/to/file/dir1/config.php | Database: db1
                              Username: user1
                              Password: pass1

Here, the length of first line is used to calculate the format of the string output, its stored in len variable.

Upvotes: 0

Related Questions