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

Это действительно самоочевидно. Я работаю в оболочке bash, и я действительно новичок в сценариях оболочки. Я нашел много информации об использовании 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. Так, например, строка «Третий pid:» должна выглядеть примерно так:

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

Остальные решения неплохие. Я часто использую вырез. Однако я просто хотел добавить, что если вы всегда хотите разбивать по пробелам, то 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