Как да разделя abcd efgh на abcd и efgh?

Това наистина се обяснява само по себе си. Работя в bash shell и наистина съм нов в скриптовете на shell. Намерих много информация за използването на tr и sed, но всички примери, които открих досега, са премахване на разделители и нови редове. Наистина искам да направя обратното на това. Искам да мога да разделя въз основа на празно място. Имам низ като "abcd efgh" и трябва да е "abcd" "efgh" (всички без кавички, само за да покажа групирането).

Сигурен съм, че това е много по-просто, отколкото го правя, но съм много объркан.

Актуализиран въпрос:

Имам колона от PID, които съм поставил в масив, но всеки елемент от масива има и двата pid в колоната.

Колона:

1234
5678

когато отпечатам целия масив, всички различни колони са добавени, така че имам всички стойности, но когато отпечатам един елемент от моя масив, получавам нещо като:

1234 5678

което не е това, което искам. Трябва да имам елемент за 1234 и отделен за 5678.

Това е моят код досега:

!/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]}"

ПРИМЕРЕН ИЗХОД:

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

Трябва всеки pid да бъде отделен, така че всеки елемент от масива да е един pid. Така например, редът "The 3rd pid is: " трябва да изглежда нещо като

The 3rd pid is: 5504

и 4-тият елемент ще бъде 4340


person ebeth    schedule 03.08.2012    source източник
comment
Как зареждате данните във вашия масив?   -  person Shawn Chin    schedule 03.08.2012
comment
@ShawnChin Току-що добави моя код по-горе. Не съм сигурен, че дори правя правилно масивите.   -  person ebeth    schedule 03.08.2012
comment
какво е jps? освен това ви липсва отваряща скоба за $myips[@]}   -  person Shawn Chin    schedule 03.08.2012
comment
И коя част от вашия скрипт не ви дава резултатите, които очаквате?   -  person Shawn Chin    schedule 03.08.2012
comment
Това наистина е частта, в която се отпечатва третият елемент от масива. Трябва ми, за да отпечатам само един от PID и вторият да бъде поставен на следващото място. Така че, ако имам три колони с по два PID, всяка имам нужда от масив от шест PID, а не масив от 3 с по два във всеки елемент. (Знам, че един от тях е дублиран, но в момента просто се опитвам да ги събера всичките в масив и тогава мога да се тревожа за дубликати).   -  person ebeth    schedule 03.08.2012
comment
for j in "${pids}" трябва да бъде for j in ${pids[@]}?   -  person Shawn Chin    schedule 03.08.2012
comment
@ShawnChin о, да, това е, което имам. Сигурно съм го написал грешно. Редактирах го, за да отрази това сега.   -  person ebeth    schedule 03.08.2012
comment
Проблемът тук е, че сте актуализирали $IFS и това обърква остатъка от вашия скрипт, който използва $IFS за разделяне на данните от колоната на елементи от масива. Вижте актуализирания отговор по-долу.   -  person Shawn Chin    schedule 03.08.2012


Отговори (6)


Опитайте cut:

$ echo "abcd efgh" | cut -d" " -f1
abcd

$ echo "abcd efgh" | cut -d" " -f2
efgh

Като алтернатива, ако в даден момент искате да направите нещо по-сложно, потърсете awk като добре:

$ echo "abcd efgh" | awk '{print $1}'
abcd

$ echo "abcd efgh" | awk '{print $2}'
efgh

За да отговорите на вашия актуализиран въпрос:

Имам колона от PID, които съм поставил в масив, но всеки елемент от масива има и двата pid в колоната.

Ако искате да заредите колона с данни в масив, можете да направите нещо подобно:

$ 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

За да отговорим на примерния код, който публикувахте, причината за вашия проблем е, че сте променили $IFS на интервал (IFS=' '), което означава, че вашите колони, които са разделени с нов ред, вече не се разделят.

Помислете за този пример:

$ 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

За да избегнете този проблем, общ подход е винаги да архивирате оригиналния IFS и да го замените, след като сте приключили с използването на актуализираната стойност. напр.

# backup original IFS
OLDIFS=$IFS

IFS=' '
# .. do stuff ...

# restore after use
IFS=$OLDIFS
person Shawn Chin    schedule 03.08.2012
comment
Много благодаря! Не осъзнавах, че актуализирането на $IFS ще означава, че новите редове вече не се броят. Вече почти работи! Когато се опитам да отпечатам целия масив, той отпечатва само последния елемент, но освен това мисля, че другият ми проблем е решен. Благодаря още веднъж, особено за обяснението какъв е проблемът ми. - person ebeth; 03.08.2012
comment
Добре дошла, Ебет. Това е често срещана грешка, която съм правил и в миналото ;) - person Shawn Chin; 03.08.2012

Примерен файл:

abcd efgh
bla blue

С помощта на awk можете да направите следното

cat file.txt | awk '{print $1}'

Това ще изведе следното

abcd
bla

or

cat file.txt | awk '{print $2}'

Това ще изведе следното

efgh
blue

Awk е наистина мощна команда, предлагам ви да опитате да я научите възможно най-скоро. Това ще ви спести много главоболия в bash скриптовете.

person Florin Stingaciu    schedule 03.08.2012
comment
Добре, има смисъл. От това, което прочетох досега, Awk изглежда изключително полезен. Ами ако искам да разделя елементите на колоната? Така че, ако исках да отделя efgh от синьото? - person ebeth; 03.08.2012
comment
@ebeth Как искаш да ги разделиш? Искаш да кажеш, че просто искаш да получиш efgh? - person Florin Stingaciu; 03.08.2012
comment
@ebeth Е, това зависи от критериите за това, което искате. Искам да кажа, че ако знаехте, че искате със сигурност „efgh“, тогава бихте могли просто cat file.txt | awk '{print $2}' | grep efgh или ако искате само първия ред cat file.txt | awk '{print $2}' | head -n 1. Всичко зависи от това защо избирате efgh. - person Florin Stingaciu; 03.08.2012

Другите решения са доста добри. Използвам cut често. Въпреки това, аз просто исках да добавя, че ако винаги искате да разделяте празно пространство, тогава xargs ще направи това вместо вас. Тогава версията на командния ред на printf може да форматира аргументите (ако се желае пренареждане на низове, използвайте awk, както в другото решение). Ето един пример за справка:

MYSTR="hello big world"
$ echo $MYSTR |xargs printf "%s : %s >  %s\n"
hello : big >  world
person infinitesteps    schedule 03.08.2012

Командата read обработва входа като цели редове (освен ако разделител не е зададен с -e):

$ echo "abcd efgh" | while read item
do
    echo $item
    # Do something with item
done

abcd efgh

Ако искате да свържете всеки елемент към команда, можете да направите следното:

echo "abcd efgh" | tr ' ' '\n' | while read item
do
    echo $item
    # Do something with item
done

abcd
efgh
person Gingi    schedule 03.08.2012

Няма нужда да използвате външни команди за разделяне на низове на думи. Вграденият set прави точно това:

string="abcd efgh"
set $string

# Now $1 is "abcd" and $2 is "efgh"
echo $1
echo $2
person Idelic    schedule 03.08.2012

Няма разлика между низа "abcd efgh" и низа "abcd" "efgh", освен че ако бъде подаден като аргумент на програма, първият ще бъде прочетен като един аргумент, докато вторият ще бъде два аргумента.

Двойните кавички " просто активират и деактивират разширението на обвивката, точно както правят единичните кавички (по-агресивно обаче).

Сега можете да имате низ '"abcd efgh"', който искате да трансформирате в '"abcd" "efgh"', което можете да направите с sed 's/ /" "/', но това вероятно не е това, което искате.

person bitmask    schedule 03.08.2012