Розщеплення рядка за першим появою роздільника


54

У мене є рядок у наступному форматі

id;some text here with possible ; inside

і хочете розділити його на 2 рядки, спочатку виникнення ;. Отже, повинно бути: idіsome text here with possible ; inside

Я знаю, як розділити рядок (наприклад, за допомогою cut -d ';' -f1), але вона розділиться на більшу частину, оскільки у мене ;всередині лівої частини.


Після розбиття рядка, що ви хочете зробити з "id"? Ви хочете призначити його змінній, роздрукувати її тощо?
Демон Хаосу

У мене будуть 2 змінні: idіstring
gakhov

Відповіді:


65

cut звучить як підходящий інструмент для цього:

bash-4.2$ s='id;some text here with possible ; inside'

bash-4.2$ id="$( cut -d ';' -f 1 <<< "$s" )"; echo "$id"
id

bash-4.2$ string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string"
some text here with possible ; inside

Але readще більше підходить:

bash-4.2$ IFS=';' read -r id string <<< "$s"

bash-4.2$ echo "$id"
id

bash-4.2$ echo "$string"
some text here with possible ; inside

3
Чудово! Це працює як шарм! Я виберу з readтих пір, як я використовую bash. Дякую @manatwork!
гахов

cutПідхід буде працювати тільки тоді , коли «$ s» не містить символів нового рядка. read є в будь-якій оболонці Борна. <<< знаходиться в rc, zsh та останніх версіях bash та ksh93 і є не стандартним.
Стефан Шазелас

На жаль, ви праві @StephaneChazelas. Мій розум був -aчомусь, коли згадували bashпро с read. (Очевидно, що тут немає ніякої користі.)
маніпуляція

Я забув зазначити, що підхід читання не працює, якщо $ s містить і символи нового рядка. Я додав власну відповідь.
Стефан Шазелас

1
Я хотів би підкреслити -f 2-в string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string"команді зворотний штрих . Це те, що ігнорує решту роздільників у рядку для роздруківки. Не очевидно, дивлячись на сторінку чоловікаcut
Стін

18

З будь-яким стандартом sh (включаючи bash):

sep=';'
case $s in
  (*"$sep"*)
    before=${s%%"$sep"*}
    after=${s#*"$sep"}
    ;;
  (*)
    before=$s
    after=
    ;;
esac

readбазовані рішення працюватимуть для однозначних значень (і з деякими оболонками, однобайтовими) значеннями, $sepвідмінними від пробілу, вкладки чи нового рядка, і лише якщо $sвони не містять символів нового рядка.

cutзасновані на роботі рішення працюватимуть лише тоді, коли $sне містять символів нового рядка.

sedМожуть бути розроблені рішення, які обробляють усі кутові випадки з будь-яким значенням $sep, але не варто йти так далеко, коли для цього вбудована підтримка в оболонці.


6

Як ви вже згадували, що ви хочете призначити значення id і string

спочатку призначте свій шаблон змінній (скажімо, str)

    str='id;some text here with possible ; inside'
    id=${str%%;} 
    string=${str#;}

Тепер у вас є свої значення у відповідних змінних


якщо ви отримуєте свій шаблон з команди, тоді використовуйте set - some_command, тоді ваш шаблон зберігатиметься в $ 1, а вищевказаний код буде використано з 1 замість str
user1678213

1
Чим ця відповідь відрізняється від @StephaneChazelas?
Бернхард

4

Окрім інших рішень, ви можете спробувати щось regexна основі:

a="$(sed 's/;.*//' <<< "$s")"
b="$(sed 's/^[^;]*;//' <<< "$s")"

або залежно від того, що ви намагаєтеся зробити, ви могли б використовувати

sed -r 's/^([^;]*);(.*)/\1 ADD THIS TEXT BETWEEN YOUR STRINGS \2/'

де \1і \2містять дві підрядки, які ви хотіли.


1

Рішення в стандартному базі:

    text='id;some text here with possible ; inside'
    text2=${text#*;}
    text1=${text%"$text2"}

    echo $text1
    #=> id;
    echo $text2
    #=> some text here with possible ; insideDD
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.