0

I got this file

root:
    admin = true
    SYSTEM = "compat"
    registry = files
    account_locked = false
    su = true
    sugroups = system,security,sec_grp

daemon:
    admin = true
    expires = 0101000070
    account_locked = true

bin:
    admin = true
    expires = 0101000070
    account_locked = true

I want to print only specific user and its attribute by using shell script. I try to use cat, grep and awk but i cannot find the solution yet.

Any Idea?

I have tested all answer with my system (Solaris 9). It doesn't work at all. I'm not sure am i do something wrong?

7 Answers7

2

Here's a quick sed solution:

sed -ne '/^daemon:/,/^$/p' filename

Which includes the blank line at the end, but is short and memorable.

Another strategy is to repeat the stanza-level data on each line to make the result friendlier to line-oriented tools, e.g.

awk '/^[a-z]/ {user=$1} (NF>1) {$1=user$1; print}' filename

Which generates this output:

root:admin = true
root:SYSTEM = "compat"
root:registry = files
root:account_locked = false
root:su = true
root:sugroups = system,security,sec_grp
daemon:admin = true
daemon:expires = 0101000070
daemon:account_locked = true
bin:admin = true
bin:expires = 0101000070
bin:account_locked = true

so you can stick a | grep whoever on the end to see that user's attributes.

Mark Reed
  • 91,912
  • 16
  • 138
  • 175
  • I like your idea. Anyway when I try with my system (Solaris 9), it doesnt work – Karin Naak-in Nov 05 '13 at 12:41
  • ...when you try, what happens? – Mark Reed Nov 05 '13 at 12:43
  • `bash-2.05# awk '/^[a-z]/ {user=$1} (NF>1) {$1=user$1; print}' aix_user.txt` `admin = true expires = 0101000070 account_locked = true admin = true expires = 0101000070 account_locked = true admin = false rlogin = false sugroups = biscore umask = 002 su = true admin = false rlogin = false sugroups = biscore umask = 002` it's seem like just cut off User Name – Karin Naak-in Nov 05 '13 at 12:49
1

You can use awk. Example:

user=daemon
awk '{if(NF==1 && $1 == "'"$user"':") {flag=1;} else if(NF>1 && flag==1) {print} else {flag=0}}' output.txt

Output:

admin = true
expires = 0101000070
account_locked = true

In this form the awk script is more readable:

{
    if(NF==1 && $1 == "'"$user"':") {
        # set a flag when the desired user name appears
        flag = 1;
    } else if (NF > 1 && flag==1) {
        # print regular lines if flag is 1
        print;
    } else {
        # if another user name appears reset the flag
        flag = 0;
    }
}
hek2mgl
  • 152,036
  • 28
  • 249
  • 266
1

With :

$ param1=root param2=registry perl -lane '
     if (/^(\w+)/) {
         $key = $1
     }
     else{
         $h->{$key}->{$F[0]} = $F[2]
     }
     END{print $h->{$ENV{"param1"}}->{$ENV{"param2"}}}
' file 

Output:

files
Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
1

Really simple with awk:

$ awk '/^daemon:$/,/^$/' file
daemon:
    admin = true
    expires = 0101000070
    account_locked = true

Or if you want the user to come from a variable, you can do:

awk -v u="$daemon" '$0 == u,/^$/' file
user000001
  • 32,226
  • 12
  • 81
  • 108
  • @sputnick The expressions says: Print all the lines from the one where the line (`$0`) is equal to the variable `u` until the empty one `^$` (`^` is the start of the line, and `$` is the end of line) – user000001 Nov 04 '13 at 21:32
1

A gnu awk version:

awk '/^daemon/' RS="\n\n" files
daemon:
    admin = true
    expires = 0101000070
    account_locked = true
Jotne
  • 40,548
  • 12
  • 51
  • 55
1

Assuming you know what the line numbers are:-

sed -n '9,12p' file > output_file

Otherwise the first answer is perfect. The first answer is probably better anyway, because it is dynamic; you will get the entire daemon stanza, regardless of how many lines it occupies. If you use line addresses and they change, then the script breaks.

petrus4
  • 616
  • 4
  • 7
1
awk '$1 == "daemon:"' RS= input-file

When RS is the empty string, awk treats paragraphs as records, and your format is conveniently laid out so that the first field ($1) is the user name.

William Pursell
  • 204,365
  • 48
  • 270
  • 300