Как получить символ в данном положении строки в сценарии оболочки?

Большинство команд имеет единственный канал ввода (стандартный вход, дескриптор файла 0) и единственный канал вывода (стандартный вывод, дескриптор файла 1) или иначе воздействует на несколько файлов, которые они открывают собой (таким образом, Вы передаете их имя файла). (Это, кроме того, от стандартной погрешности (fd 2), который обычно фильтрует полностью пользователю.) Однако иногда удобно иметь команду, которая действует как фильтр из нескольких источников или к нескольким целям. Например, вот простой сценарий, который разделяет нечетные строки в файле от четных

while IFS= read -r line; do
  printf '%s\n' "$line"
  if IFS= read -r line; then printf '%s\n' "$line" >&3; fi
done >odd.txt 3>even.txt

Теперь предположите, что Вы хотите применить другой фильтр к строкам нечетного числа и к четным строкам (но не откладывать их вместе, которые были бы другой проблемой, не выполнимой от оболочки в целом). В оболочке можно только передать стандартный вывод команды по каналу к другой команде; для передачи по каналу другого дескриптора файла необходимо перенаправить его к fd 1 сначала.

{ while … done | odd-filter >filtered-odd.txt; } 3>&1 | even-filter >filtered-even.txt

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

exec M>&N перенаправляет дескриптор файла к другому для остатка от сценария (или пока другая такая команда не изменяет дескрипторы файлов снова). Существует некоторое перекрытие в функциональности между exec M>&N и somecommand M>&N. exec форма более мощна в этом, она не должна быть вложена:

exec 8<&0 9>&1
exec >output12
command1
exec &9
command3
exec <&8

Другие примеры, которые могут представлять интерес:

И еще для большего количества примеров:

P.S. Это - удивительный вопрос, прибывающий от автора большей части сообщения upvoted на сайте, который использует перенаправление через fd 3!

23
17.03.2011, 16:56
6 ответов

В ударе с "$" Расширения Параметра {parameter:offset:length}

$ 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
37
27.01.2020, 19:42

Альтернатива расширению параметра expr substr

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

Например:

$ expr substr hello 2 1
e
6
27.01.2020, 19:42
  • 1
    , должен был проверить expr более тщательно. –  forcefsck 17.03.2011, 20:41
  • 2
    В то время как это, кажется, работает с expr от GNU coreutils, substr не включен в expr из FreeBSD, NetBSD или OS X. Это не портативное решение. –  ghoti 14.02.2017, 19:04

Puede usar el comando cortar. Para conseguir la 3ª posición:

echo "SAMPLETEXT" | cut -c3

Consulta este enlacehttp://www.folkstalk.com/2012/02/cut-command-in-unix-linux-examples.html

(Casos avanzados)Sin embargo, modificar IFS también es algo bueno, especialmente cuando su entrada puede tener espacios. Solo en ese caso, use el siguiente

saveifs=$IFS
IFS=$(echo -en "\n\b")
echo "SAMPLETEXT" | cut -c3
IFS=$saveifs
1
27.01.2020, 19:42

С zshили yashвы должны использовать:

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

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

2
27.01.2020, 19:42

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'позволяет избежать проблем с escape-символами :https://stackoverflow.com/a/40423558/895245, например.:

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

выводит \, как и ожидалось.

См. также:https://stackoverflow.com/questions/1405611/extracting-first-two-characters-of-a-string-shell-scripting

Протестировано в Ubuntu 19.04.

10
27.01.2020, 19:42

вырезание оболочки -печать определенного диапазона символов или заданной части строки

#метод1 )с использованием bash

 str=2020-08-08T07:40:00.000Z
 echo ${str:11:8}

#метод2 )с использованием разреза

 str=2020-08-08T07:40:00.000Z
 cut -c12-19 <<< $str

#метод3 )при работе с awk

 str=2020-08-08T07:40:00.000Z
 awk '{time=gensub(/.{11}(.{8}).*/,"\\1","g",$1); print time}' <<< $str
0
08.08.2020, 09:17

Теги

Похожие вопросы