如何在shell脚本中的字符串的给定位置获取char?


Answers:


36

在带有“参数扩展”的bash中$ {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



您也可以像这样设置偏移量“ from end”echo ${var: -2:1}
Vassilis

该语法来自ksh93,并且也受zshand 支持mksh
斯特凡Chazelas

6

参数扩展的替代方法是 expr substr

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

例如:

$ expr substr hello 2 1
e

很酷,应该更彻底地检查expr。
forcefsck

1
尽管这似乎可以与GNU coreutils的expr一起使用,但substr不包含在FreeBSD,NetBSD或OS X的expr中。这不是便携式解决方案。
ghoti

@ghoti,请注意,substr它最初不是GNU扩展。最初的实现expr来自70年代后期的PWB Unix,并且具有substr(但不是:)。
斯特凡Chazelas

@StéphaneChazelas,感谢您添加历史观点。:)尽管我很确定PWB的使用与OP无关,但是跟踪几十年来的功能和更改总是很有趣。GNU往往是许多人的默认设置,但总的来说,我认为我会避免使用那些不是POSIX的选项,而众所周知的选项是主要unices所缺少的。
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'为了避免转义字符出现问题: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中测试。


printf '%s' "$myvar" | cut -c2不是POSIX,因为的输出printf不是文本,除非$myvar以换行符结尾。否则,它假定变量不包含换行符,因为它会cut削减其输入的每一行
斯特凡Chazelas

awk人会更加高效,可靠,awk -- 'BEGIN {print substr (ARGV[1], 2, 1)}' "$myvar"
斯特凡Chazelas

请注意,以GNU的当前版本cut,这并不为多字节字符工作(同样为mawk或busybox的AWK)
斯特凡Chazelas

@StéphaneChazelas感谢您的观点。我不明白您在第一个中的意思:您是说那printf 'abc '| cut -c2是错误的,因为没有\n(我不知道),还是如果myvar有换行符,该命令将失败(我同意)?
Ciro Santilli新疆改造中心法轮功六四事件

1
cut如果输入的内容不是文本,则不确定其行为(尽管cut需要实现以处理行或任意长度)。的输出printf abc不是文本,因为它没有以换行符结尾。在实践中,根据实现的不同,如果将其通过管道传输到cut -c2,则会得到bb<newline>或者什么都没有。你需要printf 'abc\n' | cut -c2获得通过POSIX规定的行为(即所需的输出b<newline>
斯特凡Chazelas

1

使用zshyash,您将使用:

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

(在中zsh,您可以将其缩短为printf '%s\n' $text[3])。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.