Як отримати знак в заданому положенні рядка в сценарії оболонки?


Відповіді:


37

Нарешті на "Розширення параметра" $ {параметр: зміщення: довжина}

$ var=abcdef
$ echo ${var:0:1}
a
$ echo ${var:3:1}
d

Редагувати: Без розширення параметрів (не дуже елегантно, але це мені найперше)

$ charpos() { pos=$1;shift; echo "$@"|sed 's/^.\{'$pos'\}\(.\).*$/\1/';}
$ charpos 8 what ever here
r

1
gnu.org/software/bash/manual/… має більше деталей
jsbillings


Ви також можете встановити зсув "від кінця" такecho ${var: -2:1}
Vassilis

Цей синтаксис походить від ksh93, а також підтримується zshі mksh.
Стефан Шазелас

6

Альтернативою розширення параметрів є expr substr

substr STRING POS LENGTH
    substring of STRING, POS counted from 1

Наприклад:

$ expr substr hello 2 1
e

круто, слід було б перевірити expr ретельніше.
forcefsck

1
Хоча це, здається, працює з expr з GNU coreutils, substrале не включено в expr з FreeBSD, NetBSD або OS X. Це не портативне рішення.
ghoti

@ghoti, зауважте, що substrспочатку це не є розширенням GNU. Початкова реалізація exprприйшла від PWB Unix наприкінці 70-х і мала substr(але ні :).
Стефан Шазелас

@ StéphaneChazelas, дякую за додавання історичної перспективи. :) Хоча я впевнений, що використання PWB не має відношення до ОП, завжди цікаво відстежувати функції та зміни протягом десятиліть. GNU, як правило, є дефолтом для багатьох людей, але в цілому, я думаю, я би уникав використання параметрів, які не є явно POSIX , і, як відомо, вони відсутні у великих унісесах.
Ghoti

5

cut -c

Якщо змінна не містить нових рядків, ви можете зробити:

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

Виходи:

b

awk substr - це ще одна альтернатива POSIX, яка працює, навіть якщо змінна має нові рядки:

myvar="$(printf 'a\nb\n')" # note that the last newline is stripped by
                           # the command substitution
awk -- 'BEGIN {print substr (ARGV[1], 3, 1)}' "$myvar"

Виходи:

b

printf '%s\n'це уникати проблем із символами втечі: /programming//a/40423558/895245, наприклад:

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

Виходи, \як очікувалося.

Дивіться також: /programming/1405611/extracting-first-two-characters-of-a-string-shell-scripting

Тестовано в Ubuntu 19.04.


printf '%s' "$myvar" | cut -c2не є POSIX, оскільки висновок printfне є текстом, якщо не $myvarзакінчується символом нового рядка. Інакше передбачається, що змінна не містить символів нового рядка, оскільки cutскорочує кожен рядок її введення.
Стефан Шазелас

Той awkбув би більш ефективним та надійним ізawk -- 'BEGIN {print substr (ARGV[1], 2, 1)}' "$myvar"
Стефан Шазелас

Зауважте, що в поточних версіях GNU cutце не працює для багатобайтових символів (те саме для mawk або busbox awk)
Stéphane Chazelas

@ StéphaneChazelas дякує за очки. Я не розумів, що ви маєте на увазі в першому: ви маєте на увазі, що printf 'abc '| cut -c2це неправильно, тому що ні \n(про це я не знаю), або що команда не вдасться, якщо myvar має нові рядки (з цим я згоден)?
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

1
Поведінка cutне визначена, якщо вхідний текст не є текстом (хоча cutдля обробки рядків або довільної довжини потрібні реалізації). Вихід printf abcне є текстом, оскільки він не закінчується символом нового рядка. На практиці в залежності від реалізації, якщо ви передасте , що cut -c2ви не отримаєте ні b, b<newline>або взагалі нічого. Вам потрібно printf 'abc\n' | cut -c2буде отримати поведінку, вказану POSIX (це потрібно для виведення b<newline>)
Stéphane Chazelas

1

З zshабо yash, ви б використовували:

$ text='€$*₭£'
$ printf '%s\n' "${text[3]}"
*

zsh, ви можете скоротити його до printf '%s\n' $text[3]).


0

Можна використовувати команду cut. Щоб отримати 3 місце:

echo "SAMPLETEXT" | cut -c3

Перевірте це посилання http://www.folkstalk.com/2012/02/cut-command-in-unix-linux-examples.html

( Розширені випадки ) Однак зміна IFS також є хорошою справою, особливо коли у вашому введенні може бути пробілів. В такому випадку використовуйте наведене нижче

saveifs=$IFS
IFS=$(echo -en "\n\b")
echo "SAMPLETEXT" | cut -c3
IFS=$saveifs

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