У меня есть строка ниже:
/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | 153.2.254.229 | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand
Я новичок в Linux. Как мне разделить, используя "|" в качестве разделителя, и присвоить переменной? Я передаю всю строку как параметр и мне нужно разделить\вырезать поля по отдельности.
Например:
function()
{
while read -r record; do
## here i need the fields to cut the fields and assign to a variable #####
done < $0
}
bash -c function "/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | 153.2.254.229 | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand"
Когда я попробовал приведенный выше пример, возникла ошибка $0: ambiguous redirect
.
решение1
Вы можете использовать tr
для разделения разделитель
В следующем примере мы заменяем |
наnewline
variable=$(echo "/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | 153.2.254.229 | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand" | tr "|" "\n")
echo $variable
Вы также можете использовать
echo yourtext | tr -d "|"
Видетькоманда tr
решение2
Так много проблем помимо главной.
ambiguous redirect
это потому чтов вашем коде отсутствуют двойные кавычки.- Перенаправление с
<
берет данные из файла. Ваша строка не указывает на файл (путь). В Bash вы можете взять данные из строки с<<<
. function
— зарезервированное слово. Есть способ назвать функциюfunction
, но ее дальнейшее использование неудобно.- (терминология в вашем комментарии) Функция не является потомком.
- Функцию вызывают по имени, а не с помощью
bash -c
.Мой ответ на ваш другой вопросприменяется. - Тогда первый аргумент обозначается как
$1
, а не$0
.
Этот код работает, хотя я не уверен, что это именно то, что вам нужно:
#!/bin/bash
split_string ()
{
readarray -t arrayv < <(tr '|' '\n' <<< "$1")
}
split_string '/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | 153.2.254.229 | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand'
# now arrayv is an array variable (indexed from 0)
# retrieving few values
echo "${arrayv[0]}"
echo "${arrayv[5]}"
echo "${arrayv[9]}"
Примечания:
- Вы заключили строку в двойные кавычки. Помните, что строка в двойных кавычках подвергается определенным расширениям. Ваша строка не содержит ничего, что могло бы быть расширено (например,
$
), поэтому двойные кавычки в данном случае допустимы. В общем случае используйте одинарные кавычки для подавления расширений. readarray
является синонимомmapfile
. Призыватьhelp mapfile
к обучению.- Другие материалы для исследований:
<<<
,<( … )
,массивы. - Нет возможности передать
export
переменную массива в среду. Мы могли бы
readarray
использовать|
в качестве разделителя:readarray -t -d '|' arrayv <<< "$1"
но тогда последнее "поле" будет включать завершающий символ новой строки (он появится из-за того, как
<<<
работает). Я превращаю все разделители в новые строки с помощьюtr
, затемreadarray
использую его настройку по умолчанию (новые строки как разделители).Пробелы не принадлежат разделителям, они становятся частью хранимых значений. Используйте
sed
вместоtr
для преобразования подстрок разделителей с соседними пробелами в одиночные символы новой строки. Строкаreadarray …
будет выглядеть так:readarray -t arrayv < <(sed 's/ *| */\n/g' <<< "$1")
Если вы собираетесь использовать функцию только один раз, вам вообще не нужна функция. Эта строка (вне какой-либо функции) сделает эту работу:
readarray -t arrayv < <(tr '|' '\n' <<< '/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | 153.2.254.229 | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand')
Я определил функцию (а затем использовал ее только один раз), потому что вы попытались ее определить.
Если ваша входная строка состоит из фиксированного числа полей, и поля имеют смысл, может быть полезно назначить их разным (не массивам, обычным) переменным, имена которых имеют смысл. Пример:
IFS='|' read -r path1 path2 path3 path4 path5 ip path6 wtf1 wtf2 wtf3 extra < <(sed 's/ *| */|/g' <<< '/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | 153.2.254.229 | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand') echo "$ip" echo "$wtf3"
Конкретные примечания:
- Здесь мы явно используем
|
как разделитель. Когда мы используемread
, завершающий символ новой строки (который появляется из-за того, как работают определенные перенаправления и инструменты) не только безвреден, он необходим. - Я добавил
extra
переменную. Если полей больше, чем ожидалось, то лишние поля займутextra
. Безextra
них это повлияет на$wtf3
. - Вы можете использовать
export
эти переменные.
- Здесь мы явно используем
Если вы собираетесь манипулировать файлами/потоками, содержащими (много) записей в форме
foo|bar|baz|…
(илиfoo | bar | baz | …
похожей), то ознакомьтесь сawk
.