Спроба отримати перші 5 символів із рядка в помилці bash?


77

Я намагаюся отримати перші 5 символів із рядка, але постійно отримую Bad substitutionпомилку для рядка маніпуляції рядком, у моєму teststring.shсценарії є такі рядки :

TESTSTRINGONE="MOTEST"

NEWTESTSTRING=${TESTSTRINGONE:0:5}
echo ${NEWTESTSTRING}

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

Дякую


1
Вам пощастило? Яку версію bash ви використовуєте? ( bash -versionабо bash --version, як правило)
Alex L

4
@Mo. Я також хотів би закликати вас прийняти відповідь нижче або хоча б дати якийсь відгук. Відповідь Алекса Л дуже хороша, і це, безумовно, коштує кількох підроблених балів в Інтернеті!
Овербрид,

Відповіді:


68

Залежно від вашої оболонки, ви можете використовувати наступний синтаксис:

expr substr $string $position $length

Отже, для вашого прикладу:

TESTSTRINGONE="MOTEST"
echo `expr substr ${TESTSTRINGONE} 0 5`

Як варіант,

echo 'MOTEST' | cut -c1-5

або

echo 'MOTEST' | awk '{print substr($0,0,5)}'


52

Працює тут:

$ TESTSTRINGONE="MOTEST"
$ NEWTESTSTRING=${TESTSTRINGONE:0:5}
$ echo ${NEWTESTSTRING}
MOTES

Яку оболонку ви використовуєте?


добре, вона відмінно працює в терміналі , але він видає помилку , коли я запускаю його з .sh сценарію
Мо

5
Можливо, ваш скрипт виконується не bash, а якоюсь менш здатною оболонкою.

4
Ви пробували додати #!/bin/bashабо #!/bin/shдо свого першого рядка?
Alex L

1
Я роблю ставку .shабо #!/bin/shактивую "Режим відповідності POSIX" Bash. Оскільки ця форма нарізки рядків не є функцією оболонки POSIX (це функція Bash), вона втрачається. Спробуйте явно встановити для верхнього рядка значення #!/bin/bash, а не sh .
Zac B

1
Яку версію Bash ви використовуєте? Баш <4 бракує багато хорошого
sibaz

13

Підрядки з ${variablename:0:5}є функцією bash, недоступною в основних оболонках. Ви впевнені, що запускаєте це під bash? Перевірте рядок shebang (на початку сценарію) і переконайтеся, що це #!/bin/bashні #!/bin/sh. І переконайтеся, що ви не запускаєте його за допомогою shкоманди (тобто sh scriptname), оскільки це перевизначає shebang.


Це було одне з перших речей, які я спробував, це все одно дає ту саму помилку.
Пн.


6

Працює в більшості снарядів

TESTSTRINGONE="MOTEST"
NEWTESTSTRING=${TESTSTRINGONE%"${TESTSTRINGONE#?????}"}
echo ${NEWTESTSTRING}
# MOTES

1
Поки POSIX не приймає башизми, +1 для переносимості (хоча заголовок цього потоку вказує bash). Мені подобається бачити такі відповіді, щоб підвищити обізнаність про те, що весь світ не є поганим.
Хуан

2

Ви можете спробувати, sedякщо хочете -

[jaypal:~/Temp] TESTSTRINGONE="MOTEST"
[jaypal:~/Temp] sed 's/\(.\{5\}\).*/\1/' <<< "$TESTSTRINGONE"
MOTES

Думаю, ви маєте на увазіsed 's/\(.\{5\}\).*/\1/' <<<$TESTSTRINGONE
potong

Так, мій рядок для початку був усічений. Хворе оновлення ... Дякую @potong
jaypal singh

2

Ви були так близько! Ось найпростіше рішення:NEWTESTSTRING=$(echo ${TESTSTRINGONE::5})

Отже, для вашого прикладу:

$ TESTSTRINGONE="MOTEST"
$ NEWTESTSTRING=$(echo ${TESTSTRINGONE::5})
$ echo $NEWTESTSTRING
MOTES

1

Розширення цього параметра повинно працювати (яка версія bash у вас є?)

Ось ще один підхід:

read -n 5 NEWTESTSTRING <<< "$TESTSTRINGONE"


1

Оригінальний синтаксис буде працювати з BASH, але не з DASH. У системах debian ви можете подумати, що використовуєте bash, але, можливо, замість цього тире. Якщо / bin / dash / існує, спробуйте тимчасово перейменувати тире в щось на зразок no.dash, а потім створіть м'яке посилання, яке називається ln -s / bin / bash / bin / dash, і перевірте, чи це вирішує проблему.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.