0

Bash: Как токенизировать строковую переменную?

15

Заголовок: Как разбить строку на токены, используя пробелы в качестве разделителя?

Тело сообщения: У меня есть переменная типа строка, значение которой — "john is 17 years old". Мне нужно разбить эту строку на токены, используя пробелы в качестве разделителя. Могу ли я использовать awk для этой задачи, и если да, то как именно? Будет ли это наилучшим способом, или есть другие подходы? Спасибо заранее за помощь!

5 ответ(ов)

0

В вашем примере вы разделяете строку на токены с использованием пробелов и символа ; в Bash. Давайте разберем это по шагам.

Деление строки на токены по пробелам

Для первой строки:

$ string="john is 17 years old"
$ tokens=( $string )
$ echo ${tokens[*]}

Здесь вы создаете строку с именем string, содержащую текст "john is 17 years old". Затем вы используете массив tokens для хранения токенов, полученных из строки. По умолчанию в Bash разделитель – это пробел, поэтому строка делится на токены по пробелам. Команда echo ${tokens[*]} выведет все токены в одной строке, разделенные пробелами.

Деление строки на токены по другому разделителю, например, ;

Для разделения строки с использованием символа ;:

$ string="john;is;17;years;old"
$ OLDIFS="$IFS"
$ IFS=';' tokens=( $string )
$ echo ${tokens[*]}
$ IFS="$OLDIFS" # restore IFS

Здесь вы сначала сохраняете текущее значение переменной IFS (Internal Field Separator) в переменную OLDIFS. Затем вы изменяете значение IFS на ;, что позволяет вам разбить строку string на токены там, где находятся символы ;.

После создания массива tokens вы снова используете echo ${tokens[*]}, чтобы вывести токены в одной строке. В конце вы восстанавливаете оригинальное значение IFS, чтобы избежать нежелательных последствий в дальнейшем.

Таким образом, использование переменной IFS позволяет гибко настраивать, как именно строка будет разбиваться на токены в Bash.

0

Для использования автоматической токенизации неочищенных переменных в оболочке вы можете сделать следующее:

$ string="john is 17 years old"
$ for word in $string; do echo "$word"; done
john
is
17
years
old

Если вы хотите изменить разделитель, можете установить переменную $IFS, что обозначает "внутренний разделитель полей". Значение по умолчанию для $IFS — это " \t\n" (пробел, табуляция, новая строка).

$ string="john_is_17_years_old"
$ (IFS='_'; for word in $string; do echo "$word"; done)
john
is
17
years
old

Обратите внимание, что во втором примере я добавил круглые скобки вокруг второй строки. Это создает подсборку (sub-shell), чтобы изменение $IFS не сохранялось. Обычно вы не хотите постоянно изменять $IFS, так как это может вызвать проблемы с другими командами оболочки.

0

Вы можете использовать команду set для разделения строки на отдельные элементы, а затем получить доступ к этим элементам через позиционные параметры. Вот пример, как это делается:

$ string="john is 17 years old"
$ set -- $string
$ echo $1
john
$ echo $2
is
$ echo $3
17

В этом примере переменная string содержит строку "john is 17 years old". Команда set -- $string разбивает строку на отдельные слова и задает их как позиционные параметры. После этого вы можете получить доступ к первому ($1), второму ($2) и третьему ($3) словам с помощью команды echo. Таким образом, $1 будет равен "john", $2 — "is", а $3 — "17". Обратите внимание, что остальные слова также будут доступны в последующих позиционных параметрах.

0

Вы можете попробовать что-то вроде этого:

#!/bin/bash
n=0
a=/home/file.txt
for i in `cat ${a} | tr ' ' '\n'` ; do
   str=${str},${i}
   let n=$n+1
   var=`echo "var${n}"`
   echo $var is ... ${i}
done

Этот скрипт читает файл file.txt, разбивает его содержимое по пробелам и выводит каждое слово вместе с соответствующим номером переменной. Обратите внимание, что использование let для инкрементации переменной n не является обязательным; можно использовать простую арифметику: n=$((n + 1)). Также желательно избегать использования обратных кавычек для команд и заменить их на $(...).

Пример улучшенной версии:

#!/bin/bash
n=0
a=/home/file.txt
str=""
while read -r i; do
   str="${str},${i}"
   n=$((n + 1))
   var="var${n}"
   echo "$var is ... $i"
done < <(tr ' ' '\n' < "$a")

Этот вариант более устойчив и читабелен.

0

Вы можете использовать расширенные регулярные выражения POSIX в sed, чтобы разбить строку по несловесным символам, как в приведенном вами примере. Вот краткое объяснение кода:

str='a b     c d'
echo "$str" | sed -E 's/\W+/\n/g' | hexdump -C

В этом коде переменная str содержит строку с пробелами между словами. Команда echo передает эту строку в sed, который использует следующий шаблон:

  • s/\W+/\n/g: это заменяет последовательности несловесных символов (включая пробелы, табуляции и другие символы, исключая символ подчеркивания _) на символ новой строки (\n).

Таким образом, sed обрабатывает строку, создавая новую строку для каждого слова, и выводит результат в шестнадцатеричном формате с помощью hexdump.

Обратите внимание, что \W соответствует любому несловесному символу, включая пробелы, табуляции, символы возврата и специальные знаки, но исключает символ подчеркивания. Это означает, что snake_case (например, my_variable) будет считаться одним словом, в то время как kebab-case (например, my-variable) уже будет рассматриваться как два слова.

Также помните, что ведущие и заключительные пробелы создадут пустую строку в выводе. Это поведение будет аналогично функции re.split(r'\W+', str) в Python, где строка также будет разбита на основе несловесных символов.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь