This is really self explanatory. I'm working in a bash shell and I'm really new to shell scripting. I've found a lot of information about using tr
and sed
but all the examples I have found so far are removing delimiters and new lines. I really want to do the opposite of that. I want to be able to separate based on a blank space. I have a string like "abcd efgh" and I need it to be "abcd" "efgh" (all without quotes, just to show groupings).
I'm sure this is much simpler than I'm making it, but I'm very confused.
Updated Question:
I have a column of PIDs that I have put into an array, but each element of the array has both the pids in the column.
Column:
1234
5678
when I print out the entire array, all the different columns have been added so I have all the values, but when I print out a single element of my array I get something like:
1234 5678
which is not what I want. I need to have an element for 1234 and a separate one for 5678.
This is my code so far:
!/bin/bash
echo "Enter the File Name"
read ips
index=0
IFS=' '
while read myaddr myname; do
myips[$index]="$myaddr"
names[$index]="$myname"
index=$(($index+1))
done < $ips
echo "my IPs are: ${myips[*]}"
echo "the corresponding names are: ${names[*]}"
echo "Total IPs in the file: ${index}"
ind=0
for i in "$myips[@]}"
do
echo $i
pids=( $(jps | awk '{print $1}') )
for pid in "${pids[@]}"; do
echo $pid
done
echo "my PIDs are: ${pids}"
for j in "${pids[@]}"
do
mypids[$ind]="$j"
ind=$(($ind+1))
done
done
echo "${mypids[*]}"
echo "The 3rd PID is: ${mypids[2]}"
SAMPLE OUTPUT:
Total IPs in the file: 6
xxx.xxx.xxx.xxx
5504
1268
1
xxx.xxx.xxx.xxx
5504
4352
1
xxx.xxx.xxx.xxx
5504
4340
1
5504
1268 5504
4352 5504
4340
The 3rd pid is: 5504
4340
I need each pid to be separate, so that each element of the array, is a single pid. So for instance, the line "The 3rd pid is: " needs to look something like
The 3rd pid is: 5504
and the 4th element would be 4340
Try cut
:
$ echo "abcd efgh" | cut -d" " -f1
abcd
$ echo "abcd efgh" | cut -d" " -f2
efgh
Alternatively, if at some point you want to do something more complex, do look into awk
as well:
$ echo "abcd efgh" | awk '{print $1}'
abcd
$ echo "abcd efgh" | awk '{print $2}'
efgh
To address your updated question:
I have a column of PIDs that I have put into an array, but each element of the array has both the pids in the column.
If you want to load a column of data into an array, you could do something like this:
$ pgrep sshd # example command. Get pid of all sshd processes
795
32046
32225
$ A=(`pgrep sshd`) # store output of command in array A
$ echo ${A[0]} # print first value
795
$ echo ${A[1]} # print second value
32046
To address the example code you posted, the reason for your problem is that you've change $IFS
to a space (IFS=' '
) which means that your columns which are separated by newlines are no longer being split.
Consider this example:
$ A=(`pgrep sshd`)
$ echo ${A[0]} # works as expected
795
$ IFS=' ' # change IFS to space only
$ A=(`pgrep sshd`)
$ echo ${A[0]} # newlines no longer used as separator
795
32046
32225
To avoid this problem, a common approach is to always backup the original IFS
and replace it once you've done using the updated value. E.g.
# backup original IFS
OLDIFS=$IFS
IFS=' '
# .. do stuff ...
# restore after use
IFS=$OLDIFS
Sample file:
abcd efgh
bla blue
Using awk you can do the following
cat file.txt | awk '{print $1}'
This will output the following
abcd
bla
or
cat file.txt | awk '{print $2}'
This will output the following
efgh
blue
Awk is a really powerfull command I suggest you try to learn it as soon as you can. It will save you lots of headaches in bash scripting.
The other solutions are pretty good. I use cut often. However, I just wanted to add that if you always want to split on whitespace then xargs will do that for you. Then the command line version of printf can format the arguments (if reordering of strings is desired use awk as in the other solution). Here is an example for reference:
MYSTR="hello big world"
$ echo $MYSTR |xargs printf "%s : %s > %s\n"
hello : big > world
The read
command handles input as entire lines (unless a delimiter is set with -e
):
$ echo "abcd efgh" | while read item
do
echo $item
# Do something with item
done
abcd efgh
If you want to pipe each item to a command, you can do this:
echo "abcd efgh" | tr ' ' '\n' | while read item
do
echo $item
# Do something with item
done
abcd
efgh
No need to use external commands to split strings into words. The set
built-in does just that:
string="abcd efgh"
set $string
# Now $1 is "abcd" and $2 is "efgh"
echo $1
echo $2
There is no difference between the string "abcd efgh"
and the string "abcd" "efgh"
other than, if passed as argument to a program, the first will be read as one argument where the second will be two arguments.
The double quotes "
merely activate and deactivate shell expansion, just as the single quotes do (more aggressively, though).
Now, you could have a string '"abcd efgh"'
which you would like to transform into '"abcd" "efgh"'
, which you could do with sed 's/ /" "/'
but that's probably not what you want.
来源:https://stackoverflow.com/questions/11799666/how-do-i-split-abcd-efgh-into-abcd-and-efgh