Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Here's what I have so far:

#!/bin/bash
while read line; do
        DB=$(echo $line | cut -f1)
        USER=$(echo $line | cut -f2)
        PASS=$(echo $line | cut -f3)
        echo DB=$DB USER=$USER PASS=$PASS
done < users.txt

And a sample of the input file:

drupal_1    drupal1 tmmjXSWL
drupal_2    drupal2 FHiJSYHM
drupal_3    drupal3 b7bFNj06
drupal_4    drupal4 0AaV62EL

And output from the script:

DB=drupal_1 drupal1 tmmjXSWL USER=drupal_1 drupal1 tmmjXSWL PASS=drupal_1 drupal1 tmmjXSWL
DB=drupal_2 drupal2 FHiJSYHM USER=drupal_2 drupal2 FHiJSYHM PASS=drupal_2 drupal2 FHiJSYHM
DB=drupal_3 drupal3 b7bFNj06 USER=drupal_3 drupal3 b7bFNj06 PASS=drupal_3 drupal3 b7bFNj06

For some reason, each variable is set to the whole line. When I use echo users.txt | cut -f1 at the command line, it returns the token just fine.

share|improve this question
add comment

2 Answers

up vote 5 down vote accepted

How about this?

$ awk '{print "DB="$1"\tUSER="$2"\tPASS="$3}' users.txt
DB=drupal_1 USER=drupal1    PASS=tmmjXSWL
DB=drupal_2 USER=drupal2    PASS=FHiJSYHM
DB=drupal_3 USER=drupal3    PASS=b7bFNj06
DB=drupal_4 USER=drupal4    PASS=0AaV62EL

I can't tell if you have a problem to solve, or are wondering about a more theoretical issue.

share|improve this answer
    
Thanks, that works. I'm trying to write a script to create 40+ Drupal installations on a server for a class I'm teaching. I have scripts to setup the DBs and files, this is a piece of the script that will put it all together. The problem with my code was that the $line turned tabs into spaces as it parsed. $(echo $line | cut -d" " -f1) also works. –  mortona42 Jun 20 '12 at 23:34
add comment

The problem is in the command echo $line. Since there are no quotes around $line, the shell performs word splitting on it, then interprets each word as a globbing pattern. Try it out with

a='*.txt foo'
ls $a

In your case, the tabs separate words, which then become separate arguments to echo. The echo command prints its arguments separated by a space. So cut ends up receiving space-delimited fields instead of tab-delimited fields.

Always put double quotes around variable substitutions $foo and command substitutions $(foo) (unless you understand why you need to leave them out and why it's ok to do so). echo "$line" would work here, but it's a complicated way of doing what you propose.

Keeping your approach of parsing in the shell, you can make the read command parse the input into fields.

while read DB USER PASS; do
  echo "DB=$DB USER=$USER PASS=$PASS"
done <users.txt

read splits fields separated by characters in the value of the IFS variable, which consists of a space and a tab (plus a newline, which can't occur inside a line) by default. To split only at tabs, set IFS to a single tab first. Note that leading and trailing tabs are ignored and consecutive tabs count as a single one.

read treats \ as a special character: a backslash followed by a newline are ignored; \\ becomes a single backslash. If you want to avoid this behavior, pass the -r option.

share|improve this answer
    
+1. To set IFS to a tab char in bash: IFS=$'\t' –  glenn jackman Jun 21 '12 at 0:52
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.