Як перевірити перший символ у рядку в оболонці Bash або UNIX?


78

Я пишу сценарій в UNIX, де я повинен перевірити, чи є перший символ у рядку "/", а якщо він - гілка.

Наприклад, у мене є рядок:

/some/directory/file

Я хочу, щоб це повернуло 1, і:

server@10.200.200.20:/some/directory/file

повернути 0.


Відповіді:


140

Для цього існує багато способів. Ви можете використовувати символи підстановки у подвійних дужках:

str="/some/directory/file"
if [[ $str == /* ]]; then echo 1; else echo 0; fi

Ви можете використовувати розширення підрядків:

if [[ ${str:0:1} == "/" ]] ; then echo 1; else echo 0; fi

Або регулярний вираз:

if [[ $str =~ ^/ ]]; then echo 1; else echo 0; fi

16
Для короткого, використання: ${str::1}.
kenorb

16

Розглянемо також заяву case, яка сумісна з більшістю оболонок на основі sh:

case $str in
/*)
    echo 1
    ;;
*)
    echo 0
    ;;
esac

1
Я думав, що glob *відповідає лише одному компоненту шляху, ніколи не через косу риску/
user1011471

1
Відповідна цитата POSIX: pubs.opengroup.org/onlinepubs/9699919799/utilities/… "Умовна конструкція справи", речення ", що відповідає першому з кількох шаблонів (див. Позначення відповідності шаблонів)"
Ciro Santilli 郝海东 冠状 病 六四 事件法轮功

1
Крім того, якщо ви хочете відповідати a, #вам доведеться використовувати лапки. Наприклад: '#'*) echo "found comment";;.
Alexis Wilke

10
$ foo="/some/directory/file"
$ [ ${foo:0:1} == "/" ] && echo 1 || echo 0
1
$ foo="server@10.200.200.20:/some/directory/file"
$ [ ${foo:0:1} == "/" ] && echo 1 || echo 0
0

5
Проголосувати проти! Ви забули вказати свою змінну в одинарних дужках. foo='*'; [ ${foo:0:1} == "/" ] && echo 1 || echo 0збирається вивести цю помилку bash: [: too many arguments. Використовуйте [ "${foo:0:1}" == "/" ] && echo 1 || echo 0або навіть краще[[ ${foo:0:1} == "/" ]] && echo 1 || echo 0
Алекс-Даніель Якименко-А.

@ Алекс-Даніель Якименко-А. - відповідь devnull працює без помилок у "GNU bash, версія 4.3.48 (1) -випуск (x86_64-pc-linux-gnu) Copyright (C) 2013 Free Software Foundation, Inc."
Крейг Хікс,

Ваш початковий вираз: "Проголосувати проти! Ви забули вказати свою змінну в одинарних дужках". означає, що вирази, введені у відповідь devnulls, не працюватимуть, як на bash. Вам потрібно змінити цей початковий вираз, щоб правильно надати свою технічну суть, інакше це логічно не правильно.
Крейг Хікс,

1
@ Aleks-DanielJakimenko-A. Проголосувати проти друкарської помилки? Справді?
Mausy5043

2
@ Mausy5043 це не "друкарська помилка", вона глючить і неправильна.
Алекс-Даніель Якименко-А.

5

cut -c1

Це POSIX, і на відміну від caseнасправді витягує перший символ, якщо він вам потрібен пізніше:

myvar=abc
first_char="$(printf '%s' "$myvar" | cut -c1)"
if [ "$first_char" = a ]; then
  echo 'starts with a'
else
  echo 'does not start with a'
fi

awk substr є ще однією POSIX, але менш ефективною альтернативою:

printf '%s' "$myvar" | awk '{print substr ($0, 0, 1)}'

printf '%s'полягає у тому, щоб уникнути проблем із символами втечі: https://stackoverflow.com/a/40423558/895245 наприклад:

myvar='\n'
printf '%s' "$myvar" | cut -c1

результати, \як очікувалося.

${::} схоже не POSIX.

Дивіться також: Як витягти перші два символи рядка в сценаріях оболонки?


Чому саме printf? Це було б тому, echoщо прибирало пробіли?
Alexis Wilke

@AlexisWilke echoмає реалізації визначається поведінка на пагонах я думаю: stackoverflow.com/questions/8467424 / ...
Чіро Сантіллі郝海东冠状病六四事件法轮功
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.