Как разделить подстроку с помощью разделителя в Linux?

Как разделить подстроку с помощью разделителя в Linux?

У меня есть строка ниже:

/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

Так много проблем помимо главной.

  1. ambiguous redirectэто потому чтов вашем коде отсутствуют двойные кавычки.
  2. Перенаправление с <берет данные из файла. Ваша строка не указывает на файл (путь). В Bash вы можете взять данные из строки с <<<.
  3. function— зарезервированное слово. Есть способ назвать функцию function, но ее дальнейшее использование неудобно.
  4. (терминология в вашем комментарии) Функция не является потомком.
  5. Функцию вызывают по имени, а не с помощью bash -c.Мой ответ на ваш другой вопросприменяется.
  6. Тогда первый аргумент обозначается как $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.

Связанный контент