1

In A.csv, there are

1
2
3
4

How should I read this file and create variables $B and $C so that:

echo $B
echo $C

returns:

1 2 3 4 
1,2,3,4

So far I am trying:

cat A.csv | while read A;

do

echo $A

done

It only returns

1
2
3
4
Will Barnwell
  • 4,049
  • 21
  • 34
Chubaka
  • 2,933
  • 7
  • 43
  • 58

6 Answers6

2

Assuming bash 4.x, the following is efficient, robust, and native:

# Read each line of A.csv into a separate element of the array lines
readarray -t lines <A.csv

# Generate a string B with a comma after each item in the array
printf -v B '%s,' "${lines[@]}"

# Prune the last comma from that string
B=${B%,}

# Generate a string C with a space after each item in the array
printf -v B '%s ' "${lines[@]}"
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
1
B=$(cat A.csv)
echo $B

Output:

1 2 3 4

With quotes:

echo "$B"

Output:

1
2
3
4
Cyrus
  • 84,225
  • 14
  • 89
  • 153
  • Works for the OP's current inputs, but if one of the lines in their file has a `*` (or a line with a space), I expect that the output might be surprising to them. – Charles Duffy Sep 25 '17 at 19:36
1

As @Cyrus said

B=$(cat A.csv)
echo $B

Will output:

1 2 3 4

Because bash will not carry the newlines if the variable is not wrapped in quotes. This is dangerous if A.csv contains any characters which might be affected by bash glob expansion, but should be fine if you are just reading simple strings.

If you are reading simple strings with no spaces in any of the elements, you can also get your desired result for $C by using:

echo $B | tr ' ' ','

This will output:

1,2,3,4

If lines in A.csv may contain bash special characters or spaces then we return to the loop.

For why I've formatted the file reading loop as I have, refer to: Looping through the content of a file in Bash?

B=''
C=''
while read -u 7 curr_line; do
  if [ "$B$C" == "" ]; then
    B="$curr_line"
    C="$curr_line"
  else
    B="$B $curr_line"
    C="$C,$curr_line"
  fi
done 7<A.csv

echo "$B"
echo "$C"

Will construct the two variables as you desire using a loop through the file contents and should prevent against unwanted globbing and splitting.

Will Barnwell
  • 4,049
  • 21
  • 34
1

I would read the file into a bash array:

mapfile -t array < A.csv

Then, with various join characters

b="${array[*]}"     # space is the default
echo "$b"

c=$( IFS=","; echo "${array[*]}" )
echo "$c"

Or, you can use paste to join all the lines with a specified separator:

b=$( paste -d" " -s < A.csv )
c=$( paste -d"," -s < A.csv )
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • `mapfile` and `readarray` are synonyms and only available in version >4.0, the `paste` solution is neat and 3.x compatible! – Will Barnwell Sep 25 '17 at 20:59
0

Try this :

cat A.csv | while read A;

do

printf "$A"

done

Regards!

Matias Barrios
  • 4,674
  • 3
  • 22
  • 49
  • 1
    Eh? There won't be any newlines in this usage, and it'll also mangle your output if it contains format escapes. Perhaps you want `printf '%s ' "$A"`, to print a space after each, and then `printf '\n'` at the end? – Charles Duffy Sep 25 '17 at 19:32
  • And the `cat` is nothing but overhead -- leaving it out and using ` – Charles Duffy Sep 25 '17 at 19:33
0

Try This(Simpler One):

b=$(tr '\n' ' ' < file)
c=$(tr '\n' ',' < file)

You don't have to read File for that. Make sure you ran dos2unix file command. If you are running in windows(to remove \r).

Note: It will modify the file. So, make sure you copied from original file.

Abhinandan prasad
  • 1,009
  • 7
  • 13