Register
It is currently Fri Nov 21, 2014 2:24 am

Trouble reordering fields.


All times are UTC - 6 hours


Post new topic Reply to topic  [ 6 posts ] 
Author Message
 PostPosted: Mon Feb 20, 2012 10:45 am   

Joined: Tue Feb 14, 2012 6:15 pm
Posts: 6
I am trying to write a script that will do a home directory search for a few key words and send the results to a temp file. So far, no problem. Then I want to take the info in the temp file and output it to the screen in a different format.... Problem. I am not asking for anyone to write the script for me (although example syntax would be great), I am just looking for ideas as to how to go about it. I would prefer to NOT use awk.
I get this format in my tempfile:
/home/user1/filewithblue:The sky is blue.
/home/user2/filewithred: The car is red.
/home/user3/filewithgreen: The grass is green.
But I want this format to output to the screen:
user1 - The sky is blue. - /home/user1/filewithblue
user2 - The car is red. - /home/user2/filewithred
user3 - The grass is green. - /home/user3/filewithgreen
I only use one example per user but there will be multiple lines for each. I am also wondering what command I would use to put an empty line (or two) in between the different users to keep them separate. I am assuming a for / do is what I need but I am having trouble figuring out how to put it together.

Any and all suggestions will be appreciated.


Top
 Profile  
 PostPosted: Sat Mar 31, 2012 8:10 pm   
User avatar

Joined: Wed Jun 08, 2011 8:27 am
Posts: 189
Location: outer Shpongolia
nosaj wrote:
[...] I am just looking for ideas as to how to go about it. I would prefer to NOT use awk.
I get this format in my tempfile:
/home/user1/filewithblue:The sky is blue.
/home/user2/filewithred: The car is red.
/home/user3/filewithgreen: The grass is green.
But I want this format to output to the screen:
user1 - The sky is blue. - /home/user1/filewithblue
user2 - The car is red. - /home/user2/filewithred
user3 - The grass is green. - /home/user3/filewithgreen


Use a while/read loop to retrieve the two main fields (path and string found), delimited by a
colon, in different variables ( e.g., « path » and « srch » ), and some parameter expansions
to extract the username from the path, for each line read from the temporary file. The process
consists of removing the filename which is in the path, then store the result to remove what's in
front of the username, from the modification, to get solely the string that represents the name of
the user. Note that if your grep(1) search was recursive, it'll fail and you'll get either a filename or
a directory name, instead of the username, so let's have another approach that will work: remove
the string « /home/ » from the path, then remove what's to its right.

Now that you have every information needed stored in multiple variables, display them in your
desired format simply by expanding them and adding hyphens wherever you want them to be.


Code:
while IFS=' :' read -r path srch _; do
    tmp=${path#*/*/}
    printf '%s - %s - %s\n' "${tmp%%/*}" "$srch" "$path"
done < tempfile

________


nosaj wrote:
I only use one example per user but there will be multiple lines for each. I am also
wondering what command I would use to put an empty line (or two) in between
the different users to keep them separate.

[2] nosaj wrote:
I would prefer to NOT use awk.


It becomes tricky without awk(1), and the solution won't fit with this forum's part ( i.e., « General suggestions and the VERY basics » ).
I'll try to explain how I approached this problem by detailing the following code line per line, though.

Here is the code :

Code:
declare -A users

while IFS=' :' read -r path srch; do
    tmp=${path#*/*/} u_name=${tmp%%/*}
    printf -v sp '%*s' $((${#u_name} + 3))
   
    if ((! ${#users["$u_name"]})); then
        unset 'sp'
    fi 
    users["$u_name"]+="$sp$srch - $path"$'\n'
done < tempfile

for u in "${!users[@]}"; do
    printf '%s - %s\n' "$u" "${users[$u]}"
done


  1. Declare the variable called users as an associative array.
    It'll be used to store each path and string according to one username ;
    -
    -
  2. Retrieve the path and string found from each tempfile's line in
    the variables path and srch respectively ;
    -
  3. Extract the part of the path corresponding to the username thanks to
    two parameter expansions. The variable tmp will contain the path
    minus the string « /home/ », and the variable u_name will contain
    the username ;
    -
  4. Assign spaces to the variable called sp. The number of spaces is
    determined by the size of the username retrieved, to which we add 3
    (because there are three characters in between the username's last
    character and the string's first one), to align the different informations
    next to the username's right side, instead of displaying them below it ;
    -
  5. Test whether the part corresponding to the username found on the line,
    stored in the array users, is empty, so that its size is 0 ;
    -
  6. If it is actually empty, then we unset the variable sp which contains the
    spaces to make the alignment, because it means that there is no other
    information before the one being read, so there is nothing to format ;
    -
  7. ( End of the test ; )
    -
  8. Append the fields which are meant to be after the username, with
    the desired format, to the space dedicated for the actual username
    in the array users. Each new pair of fields is separated by a newline
    and padded with spaces stored in the variable sp to make the alignment ;
    -
  9. ( Redirect stdin ( file descriptor 0 ) to read input from the file called tempfile ; )
    -
    -
  10. Loop through every index ( usernames ) of the array users ;
  11. Display the username, followed by the elements associated with it ;
  12. ( End of the loop. )


Top
 Profile  
 PostPosted: Sat Apr 14, 2012 11:21 pm   

Joined: Tue Feb 14, 2012 6:15 pm
Posts: 6
Thanks for your reply. This is what I ended up with. I am a novice so I am sure it could have been done smoother.

First I put the whole script inside a function.

Then I did a count on the number of lines in the file.
NUMB=`wc -l "path" | cut -f1 -d ' '`
Did a check to see if it was empty. Allowing an exit if it was.
if [[ $NUMB = 0 ]]; then echo "Done."; fi; exit
Then I used the head command to take the first line from the file.
LINE=`head -n1 "path"`
Then I cut the line up and assigned variables.
ONE=`head -n1 "path" | cut -f3 -d '/'`
TWO=`head -n1 "path" | cut -f2 -d ':'`
THREE=`head -n1 "path" | cut -f1 -d ':'`
Then I called the variables back.
echo ONE: "$ONE"; echo; echo TWO: "$TWO"; echo; echo THREE: "$THREE"
Deleted the first line from the file. Now the second is the first and there is one less line in the file.
sed -i '1d' "path"
And then called the function again.

It's not pretty but it worked for me.


Top
 Profile  
 PostPosted: Sun Apr 15, 2012 5:54 am   

Joined: Mon Mar 02, 2009 3:03 am
Posts: 567
hi,

variables are useless here.


Top
 Profile  
 PostPosted: Tue Apr 24, 2012 8:59 pm   

Joined: Tue Feb 14, 2012 6:15 pm
Posts: 6
Watael wrote:
hi,

variables are useless here.



Can you explain? How else are you going to get the output to the screen unless you assign a variable to call back?

Thanks


Top
 Profile  
 PostPosted: Tue Apr 24, 2012 11:10 pm   

Joined: Mon Mar 02, 2009 3:03 am
Posts: 567
Code:
echo -n "ONE: "
head -n1 "path" | cut -f3 -d '/'`


Top
 Profile  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  


BashScripts | Promote Your Page Too
Powered by phpBB © 2011 phpBB Group
© 2003 - 2011 USA LINUX USERS GROUP