Невозможно получить пустую подстроку, если токен не найден в bash - PullRequest
2 голосов
/ 15 января 2020

Я пытаюсь получить подстроку после токена "-" в bash

У меня есть следующая функция:

STR="abc-def"
END=`echo $STR | cut -d "-" -f2`
echo $END # prints def (OK)

STR="abc"
END=`echo $STR | cut -d "-" -f2`
echo $END # prints abc (ERROR)

STR="abc-abc"
END=`echo $STR | cut -d "-" -f2`
echo $END # prints abc (OK)

Как это исправить, чтобы, когда я не найти "-" Я получаю END = ""?

Ответы [ 3 ]

4 голосов
/ 15 января 2020

ОБНОВЛЕНИЕ : В своем оригинальном решении я ошибочно предположил, что `END 'должен оставить начальный дефис, и я только что заметил, что это не так. Теперь я обновил свое решение, и новая версия стала немного проще:

Нет необходимости создавать дочерний процесс здесь. По сути, вы можете сделать

END=${STR#*-}

шаблон глобуса после #, удаляющий все до первого -. Это по-прежнему оставляет проблему открытой: если STR не содержит переноса, вы получите исходную строку, а не пустую строку.

Поскольку вы отметили свой вопрос как bash и shell , я предложу решения для обоих.

В bash вы можете просто сделать

if [[ $STR == *-* ]]
then
  END="${STR#*-}"
else
  END=
fi

, поскольку [[ не является внешняя команда, для этого также не требуется подпроцесс.

В оболочке POSIX я бы сделал

END="${STR#*-}" # Remove up to (including) hyphen
if [ "$END" = "$STR" ]
then
  # We did not have a hyphen
  END=
fi

Это порождает один подпроцесс ([), так что это дороже, чем версия bash.

1 голос
/ 15 января 2020

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

[[ "${STR}" == *"-"* ]] && END=$(echo $STR | cut -d "-" -f2) || END = ""

Если вы предпочитаете (в данном случае не очень крипт c) regexp aproach:

[[ "${STR}" =~ "-" ]] && END=$(echo $STR | cut -d "-" -f2) || END = ""
0 голосов
/ 15 января 2020

Изменить '-' на ''

STR=${STR//-/' '}

Преобразовать STR в массив

STR=( $STR )

Назначить 2-й элемент END

END=${STR[1]}

Если 2-й элемент существует END будет 'def', если нет, тогда END будет пустым. Oneliner

STR="abc-def"; STR=( ${STR//-/' '} ); END=${STR[1]}; echo $END

И в случае пробелов слева / справа или с обеих сторон, смена IFS может помочь

IFS=-; STR='ab x-de f'; ARR=( $STR ); END=${ARR[1]}; echo $END

Или вы можете конвертировать пробелы и в конце концов конвертировать их обратно

STR='ab x-de f'; STR=${STR//' '/_SPACE_}; STR=${STR//-/' '}; ARR=( $STR ); END=${ARR[1]}; echo ${END//_SPACE_/' '}
...