0

I have a file that contains 10 lines with this sort of content: aaaa,bbb,132,a.g.n.

I wanna walk throw every line, char by char and put the data before the " , " is met in an output file.

    if [ $# -eq 2 ] && [ -f $1 ]
then
    echo "Read nr of fields to be saved or nr of commas."
    read n
    nrLines=$(wc -l < $1)
    while $nrLines!="1" read -r line || [[ -n "$line" ]]; do
    do
        for (( i=1; i<=$n; ++i ))
        do
            while [ read -r -n1 temp ]
            do
                if [ temp != "," ]
                then
                    echo $temp > $(result$i)
                else

                fi
            done

            paste -d"\n" $2 $(result$i)
        done
        nrLines=$($nrLines-1)
    done
else
    echo "File not found!"
fi

}

In parameter $2 I have an empty file in which I will store the data from file $1 after I extract it without the " , " and add a couple of comments.

Example:
My input_file contains:
a.b.c.d,aabb,comp,dddd
My output_file is empty.

I call my script: ./script.sh input_file output_file
After execution the output_file contains:
First line info: a.b.c.d
Second line info: aabb
Third line info: comp

(yes, without the 4th line info)
Marko
  • 407
  • 1
  • 7
  • 19
  • At the beginning of your post, you say you want to put the data in a variable, but then in your code you simply put it into a file. If you want to store each field into a separate variable use 'cut' and if you want to parse the whole file and split it into a new file with newlines instead of commas, use 'tr'. – Nick Mar 28 '16 at 08:53

6 Answers6

0

To print 2016 th line from a file named file.txt u have to run a command like this-

sed -n '2016p' < file.txt

More-

sed -n '2p' < file.txt

will print 2nd line

sed -n '2011p' < file.txt

2011th line

sed -n '10,33p' < file.txt

line 10 up to line 33

sed -n '1p;3p' < file.txt

1st and 3th line

and so on...


For more detail, please have a look in this tutorial and this answer.

Community
  • 1
  • 1
Abrar Jahin
  • 13,970
  • 24
  • 112
  • 161
  • Ok. I want to know hot to ignore the comma while walking throw an array. How to increment my char counter. – Marko Mar 28 '16 at 08:45
  • Please have a look in here- http://stackoverflow.com/questions/29642102/how-to-make-awk-ignore-the-field-delimiter-inside-double-quotes And use that with pipelining with this answer's answer – Abrar Jahin Mar 28 '16 at 08:51
  • About pipelines, can be found here- http://www.gnu.org/software/bash/manual/html_node/Pipelines.html – Abrar Jahin Mar 28 '16 at 08:52
  • If u find my answer helpful, please accept it so that we both can have some points – Abrar Jahin Mar 28 '16 at 08:52
  • I dont think I understand. I want to manipulate a single line. I read a char, I put it in a variable. If the char that I read is " , " I want to ignore it and get to the next char. I dont need to jump throw file lines, I just need to move with 1 position in advance. – Marko Mar 28 '16 at 08:53
0
[wspace@wspace sandbox]$ awk -F"," 'BEGIN{OFS="\n"}{for(i=1; i<=NF-1; i++){print "line Info: "$i}}' data.txt
line Info: a.b.c.d
line Info: aabb
line Info: comp

This little snippet can ignore the last field.

updated:

#!/usr/bin/env bash


if [ ! -f "$1" -o $# -ne 2 ];then
    echo "Usage: $(basename $0) input_file out_file"
    exit 127
fi

input_file=$1
output_file=$2

: > $output_file

if [ "$(wc -l < $1)" -ne 0 ];then
    while true
    do
        read -r -n1 char
        if [ "$char" == "" ];then
            break
        elif [ $char != "," ];then
            temp=$temp$char
        else 
            echo "line info: $temp" >> $output_file
            temp=""
        fi
    done < $input_file
else
    echo "file $1 is empty"
fi

Maybe this is what you want

huihoo
  • 1
  • 2
  • I thought the OP comment about the fourth line missing was a bug! You're right, 'awk' is the best way. – Nick Mar 28 '16 at 08:58
  • I understand your aproach, but the idea here is not to solve the problem in a different way, but to indicate how can I navigate one step further in the array. What should I write on the else, there where I have a # line. – Marko Mar 28 '16 at 09:06
  • variable `result` contains what?Your purpose is to split a line separated by comma to multiple lines(ignored the last filed), then store them to a file called `$result$i`, 10 lines to 10 files, right? – huihoo Mar 28 '16 at 09:17
  • I have updated the code so that the last line will not be taken into account. – Marko Mar 28 '16 at 09:17
  • Can you tell us what you want to do more clearly,including complete input_file and output_file.:) – huihoo Mar 28 '16 at 09:20
  • Your solving indications are correct. But the exposed problem was just for the sake of presenting my main problem that is: incrementing the position on which i am with the check. Let's say we have a vector V with dimension = 10. I am situated on V[i] and i wanna jump on V[i+1]. See the commented else branch. – Marko Mar 28 '16 at 09:27
0

In native bash the following should do what you want, assuming you replace the contents of your script.sh with the below:

#!/bin/bash

IN_FILE=${1}
OUT_FILE=${2}
IFS=\,

while read line; do
        set -- ${line}
        for ((i=1; i<=${#}; i++)); do
                ((${i}==4)) && continue
                ((n+=1))
                printf '%s\n' "Line ${n} info: ${!i}"
        done
done < ${IN_FILE} > ${OUT_FILE}

This will not print the 4th field of each line within the input file, on a new line in the output file (I assume this is your requirement as per your comment?).

Ell
  • 927
  • 6
  • 10
0

Try this (tested with you sample line) :

#!/bin/bash
# script.sh
echo "Number of fields to save ?"
read nf

while IFS=$',' read -r -a arr; do
  newarr=${arr[@]:0:${nf}}
done < "$1"

for i in ${newarr[@]};do
  printf "%s\n" $i 
done > "$2"

Execute script with :

$ ./script.sh inputfile outputfile
Number of fields ?
3
$ cat outputfile
a.b.c.d
aabb
comp

All words separated with commas are stored into an array $arr

A tmp array $newarr removes last $n element ($n get the read command).

It loops over new array and prints result in $2, the outputfile.

SLePort
  • 15,211
  • 3
  • 34
  • 44
0

Did you try

sed  "s|,|\n|g" $1 | head -n -1 > $2

I assume that only the last word would not have a comma on its right.

Till
  • 4,183
  • 3
  • 16
  • 18
0

You can do what you want very simply with parameter-expansion and substring-removal using bash alone. For example, take an example file:

$ cat dat/10lines.txt
aaaa,bbb,132,a.g.n.
aaaa,bbb,133,a.g.n.
aaaa,bbb,134,a.g.n.
aaaa,bbb,135,a.g.n.
aaaa,bbb,136,a.g.n.
aaaa,bbb,137,a.g.n.
aaaa,bbb,138,a.g.n.
aaaa,bbb,139,a.g.n.
aaaa,bbb,140,a.g.n.
aaaa,bbb,141,a.g.n.

A simple one-liner using native bash string handling could simply be the following and give the following results:

$ while read -r line; do echo ${line%,*}; done <dat/10lines.txt
aaaa,bbb,132
aaaa,bbb,133
aaaa,bbb,134
aaaa,bbb,135
aaaa,bbb,136
aaaa,bbb,137
aaaa,bbb,138
aaaa,bbb,139
aaaa,bbb,140
aaaa,bbb,141

Paremeter expansion w/substring removal works as follows:

var=aaaa,bbb,132,a.g.n.

Beginning at the left and removing up to, and including, the first ',' is:

${var#*,}     # bbb,132,a.g.n.

Beginning at the left and removing up to, and including, the last ',' is:

${var##*,}    # a.g.n.

Beginning at the right and removing up to, and including, the first ',' is:

${var%,*}     # aaaa,bbb,132

Beginning at the left and removing up to, and including, the last ',' is:

${var%%,*}    # aaaa

Note: the text to remove above is represented with a wildcard '*', but wildcard use is not required. It can be any allowable text. For example, to only remove ,a.g.n where the preceding number is 136, you can do the following:

${var%,136*},136  # aaaa,bbb,136  (all others unchanged)
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85