Parse CSV in bash and assign variables
Try a loop:
while IFS=, read dn mac partition
do
echo "Do something with $dn $mac and $partition"
done < file
To select a record you could use a case statement:
P2=123
while IFS=, read dn mac partition
do
case $dn in
($P2) echo echo "Do something with $dn $mac and $partition" ;;
(*) echo "Do nothing" ;;
esac
done < file
shell parse csv file, assign fields to variable and print it in multiple columns
awk is certainly the correct tool to use for this, but you can also do:
curl http://example.com/1.txt |
while IFS=, read ip type name rest; do
echo $ip $type $name
done
The variables will lose their value after the while loop finishes, since it is in a sub-shell.
How to parse a CSV file in Bash?
You need to use IFS
instead of -d
:
while IFS=, read -r col1 col2
do
echo "I got:$col1|$col2"
done < myfile.csv
Note that for general purpose CSV parsing you should use a specialized tool which can handle quoted fields with internal commas, among other issues that Bash can't handle by itself. Examples of such tools are cvstool
and csvkit
.
Bash: Parse CSV and edit cell values
See Why is using a shell loop to process text considered bad practice?
As question is tagged linux
, assuming GNU sed
is available. And also that the input is actually csv
, not space/tab separated
$ cat ip.csv
ID,Location,Way,Day,DayTime,NightTime,StandNo
1,abc,Up,mon,6.00,18.00,6
2,xyz,down,TUE,2.32,5.23,4
$ sed '2,$ {s/[^,]*/\L\u&/4; s/[^,]*/\U&/3; s/[^,]*/\U&/2}' ip.csv
ID,Location,Way,Day,DayTime,NightTime,StandNo
1,ABC,UP,Mon,6.00,18.00,6
2,XYZ,DOWN,Tue,2.32,5.23,4
2,$
to process input from 2nd line to end of files/[^,]*/\L\u&/4
capitalize only first letter of 4th fields/[^,]*/\U&/3
capitalize all letters in 3rd fields/[^,]*/\U&/2
capitalize all letters in 2nd field
If the fields themselves can contain ,
within double quotes and so on, use perl
, python
, etc which has csv
modules
Bash Read CSV value from Variable in Bash
"192.168.1.1,192.168.100.1"
Here is your issue. The problem is that when the while loop is reading, after the first iteration there is no more commas so it hits the end and quits. "192.168.1.1,192.168.100.1,"
should show the way you are intending.
As other's have suggested in the comments, I would go with a for loop myself, but to with closet to how you were trying to implement it, this would work for you:
IP_PING="192.168.1.1,192.168.1.2,192.168.1.3"
while read -r ip1 ; do
ping -c 4 "$ip1" >/dev/null
if [ $? -ne 0 ]; then
echo "Ping fail"
else
echo "Ping success"
fi
done < <(echo $IP_PING |tr ',' '\n')
< <(echo $IP_PING |tr ',' '\n')
is process substitution. To put it simply it will "pipe" the output into the while loop. The difference from a normal pipe being that it creates one less process; the actual pipe creates a process itself.
Using process substitution will also keep the while loop in the current environment as well. (vs a while loop usually takes a 'snapshot' of the env and uses that during the loop, then it disappears when the loop ends) Meaning, with process substitution, that processes in the while loop will be able to see changes in env variables of the parent while it is looping, AND variables assigned within the loop will also still be available in the parent after it ends.
Read input from a csv and append that values to variable using shell script
I don't see anything in your code that would cause your script to only show the last value.
This may be an illusion: is your dir.csv
file CRLF-delimited? (DOS/Windows format) If so, remove the CR that ends each line with a utility like dos2unix
or a command like tr -d '\r'
.
Some notes though:
- In
Dir+="Dir,$line"
, the stringDir
should probably be removed (Dir+=",$line"
). - You probably want to get rid off the initial comma:
Dir=${Dir#,}
. - All this can be simplified with the single command below:
Dir=$(paste -s -d, dir.csv)
... or, with CRLF line-endings:
Dir=$(tr -d '\r' < dir.csv | paste -s -d,)
How to parse a CSV in a Bash script?
First prototype using plain old grep
and cut
:
grep "${VALUE}" inputfile.csv | cut -d, -f"${INDEX}"
If that's fast enough and gives the proper output, you're done.
Related Topics
Use Sudo Inside Dockerfile (Alpine)
Run Command 'At ' 5 Seconds from Now
Match All Files Under All Nested Directories with Shell Globbing
Debugging in Pycharm with Sudo Privileges
What Tools Do I Need to Develop in Actionscript (In Linux)
When and How Are System Calls Interrupted
How to Debug Mex Code with Eclipse
How to Delete Everything in a String After a Specific Character
How to Run Linux Docker Images on Windows Server 2016
Arm Linux Atags VS Device Tree
How Does Stat Command Calculate the Blocks of a File
Udev - Run Program on Usb Flash Drive Insert
Poll(2) Doesn't Empty the Event Queue
Linux/Perl: Additional Output Buffers Other Than Stdout and Stderr
What Does the Gcc Error Message, "Error: Unsupported for 'Mov'", Mean
How to Connect to Jenkins Server (Amazon Linux Ami)
How to Interpret Segment Register Accesses on X86-64
Linux Terminal: How to Capture or Watch Other Terminal Session