Pregunta

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

¿Fue útil?

Solución

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

Otros consejos

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top