• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 119
  • Last Modified:

Parsing a file using ksh

I have a file that looks like this:

uid=name
userpassword={crypt}nJEKEgaHjJZY2
uid=john
userpassword={crypt}nJEKEgaHjJZY2
uid=bill
userpassword={crypt}nJEKEgaHjJZY2

Of course the hash will be different on the userpasswords.  What I want to do is read this file and write it out to another file in this format:

name      nJEKEgaHjJZY2
john        nJEKEgaHjJZY2
bill           nJEKEgaHjJZY2

Any help would be appreciated.  Again, of course the userpasswords are unique, but they all have the {crypt} in front of them.  I got this far, but I can't get it to read through the whole file.

servername-[root]/home/share/david/work> jane=$(cat file | cut -d= -f2 | sed s/{crypt}//g)
servername-[root]/home/share/david/work> echo $jane
oracle nJEKEgaHjJZY2

Thanks!
David
0
David Aldridge
Asked:
David Aldridge
  • 6
  • 4
1 Solution
 
David AldridgeAuthor Commented:
I figured it out.  If someone has a better way, I'd be glad to award the points for it.  I'll leave it open for a bit.

#/usr/bin/ksh
# set -x
count=1

while read -r line
do
        if [[ $count = 1 ]]
        then
                first=$(echo $line | cut -d= -f2 | sed s/{crypt}//g)
                count=$(( $count + 1))
                continue
        else
                second=$(echo $line | cut -d= -f2 | sed s/{crypt}//g)
                echo "$first\t$second"
                count=1
        fi
done < file
0
 
tel2Commented:
Hi David,

I don't know whether this is "better", but it's more concise and should be a lot faster:

sed 'N;s/\n//;s/uid=//;s/userpassword={crypt}/\t/' file

Output:
name        nJEKEgaHjJZY2
john        nJEKEgaHjJZY2
bill        nJEKEgaHjJZY2

Put it in a ksh script if you wish.

If you don't like the above, will you accept Perl solutions?

tel2
1
 
tel2Commented:
P.S. If you decide to stick with your solution, note:
- The /g modifiers in the sed commands are not necessary.  Try: sed s/{crypt}//
- If you want a real tab character to appear between output fields, use the -e switch: echo -e "$first\t$second"
- The "continue" line is not necessary in this case.
- Your "count=$(( $count + 1))" line could be simplified to:
    count=$((count + 1))
   OR:
    let count=$count+1
- Your "while read -r line" line could be just "while read line" unless the input could contain back-slashes.
- I used to use ksh, but I'd recommend use bash if it is available to you.  It's more modern and powerful, and I think most ksh code will run in bash.
1
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
tel2Commented:
Here's a slightly different alternative sed approach:

sed 'N;s/uid=\(.*\)\nuserpassword={crypt}\(.*\)/\1\t\2/' file
1
 
tel2Commented:
P.S. If you ever want to trace the execution of an entire script, you don't need to put this at the start:
    set -x
You can just run the script like this:
    ksh -x scriptname
or:
    bash -x scriptname
This means you don't need to waste time editing the script before and after you do your debugging.
But "set -x" still has its place, because it allows you to turn on debugging from a specific point in the code.
1
 
David AldridgeAuthor Commented:
Great stuff!  If you have time or care to shoot a Perl solution, that would be great.  If you don't, that's fine.  I understand the time thing!

Thanks again!
David
0
 
David AldridgeAuthor Commented:
Excellent!
0
 
tel2Commented:
Thanks for the points, David.

Here are 3 Perl solutions:

# Read file line by line removing unwanted text
perl -pe 's/^uid=(.*)\n/$1\t/;s/^userpassword={crypt}//' file

# Read entire file (slurp) then remove unwanted text with a global substitution
perl -0pe 's/^uid=(.+)\nuserpassword={crypt}(.+)/$1\t$2/mg' file

# Read entire file (slurp) then print wanted parts a while loop
perl -0ne 'print "$1\t$2\n" while(/^uid=(.+)\nuserpassword={crypt}(.+)/mg)' file

But each of the above could also be written as traditional Perl scripts (rather than one-liners), and could also be embedded in a shell script as a one-liner or an in-line Perl script (here document).

Too bad I don't understand the time thing yet.    8)

Any questions about the above?
0
 
David AldridgeAuthor Commented:
Absolutely brilliant!  Thank you so much for your help. I've had a subscription here since Jan 3, 2001.  It's answers like these that make every dollar with it.  Thank you my friend.
0
 
tel2Commented:
Thanks David,

I prefer Perl because it's flexible enough to be used for almost anything (including the coding behind websites, which is what I sometimes use it for), and I know it better than sed, awk, etc.  But the sed solutions might be slightly more efficient for problems like yours.

A pleasure doing business, David.

Please hold while I give myself a pay rise for confusing you with 5 solutions instead of 1...
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

  • 6
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now