![ksh88 中可以使用 Here-Strings 吗?](https://linux22.com/image/135383/ksh88%20%E4%B8%AD%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%20Here-Strings%20%E5%90%97%EF%BC%9F.png)
我想从 ksh 脚本中 3 个不同变量中的一个变量中提取 3 个单词。我在 ksh93 上使用了这条线,效果很好:
read A B C <<< $line
在 ksh88 上运行上述命令时出现此错误:
syntax error at line ## : '<' unexpected
如何在 ksh88 上执行相同的操作?
答案1
ksh88
不,这里的字符串在和上不可用pdksh
。然而,在最近的ksh93
(原始 AT&T Korn Shell)和mksh
(目前正在积极开发的pdksh
衍生产品)上,它是可用的。
<<<
是ksh93
、mksh
、 GNUbash
和zsh
.
你的具体问题...
read A B C <<< $line
…可以用这个解决(Korn shell):
print -r -- $line |&
read -p A B C
您也可以使用这个(POSIX shell),但它有 tmpfile 性能损失(另一方面,<<<
也可能有):
read A B C <<EOF
$line
EOF
但是,如果您只想拆分单词:
set -A arrname -- $line
然后使用${arrname[0]}
代替$A
和${arrname[1]}
代替$B
。只是它不会在分裂到三个元素时停止,所以如果$line
是“ foo bar baz bla
”,$C
将包含“baz bla”,而${arrname[2]}
有“baz”并且${arrname[3]}
有“bla”。
不过,如果您不需要位置参数,您可以这样做
set -- $line
A=$1; shift
B=$1; shift
C=$*
但是,如果单词少于三个,则会导致错误(如果不确定,请检查,shift
或者首先使用(可能会更慢)进行检查)。$line
$#
[[ $line = *' '*' '[! ] ]]
请注意,这set … $line
也会进行通配符(感谢 Stéphane 提醒我们),因此您需要set -o noglob
之前(通常之后可能会恢复之前的状态set +o noglob
)。
完全披露:我是mksh
开发人员。
答案2
不,here-strings 来自zsh
1991 年的 2.0(和/或 的 Unix 端口rc
,他们各自的作者在那时交换了想法,目前尚不清楚两人中哪一个有这个想法或首先将其包含在他的 shell 中)。
它在 2.05b (2002) 中添加到 bash,在 m+ (2002) 中添加到 ksh93,在 R33 (2008) 中添加到 mksh,在 2.7 (2009) 中添加到 yash。
ksh88 没有获得任何新功能。
这里的文档 ( <<
) 本身来自 70 年代末的 Bourne-shell。
read A B C
读一逻辑的以一种非常特殊的方式将行插入A
,B
和C
变量(稍微不那么特别,$IFS
它的默认值仅包含 IFS 空白字符1),反斜杠充当转义和行继续字符,这将C
变得非常复杂以及。如果没有的话做同样的事情read
会非常困难。
无论如何,这里的<<<
与 一样<<
,只有语法差异。
read A B C << EOF
$var
EOF
完全一样
read A B C <<< "$var" # note that some versions of bash need the quotes
在所有贝壳中。对于这两种情况,shell 都会创建一个已删除的临时文件,其中包含内容和一个附加换行符(尽管有些 shell 使用管道代替)。然后read
读一逻辑的行(可能在几个以反斜杠继续的物理行上)并使用其复杂的规则填充变量。
$var
它仅分配to的前 3 个字(SPC/TAB 分隔)$A
,$B
并且 $C
如果
$IFS
仍然包含其默认值- 该变量不包含反斜杠和换行符
- 该变量仅包含 3 个单词。
对于前三个词,你可以这样做:
function split_into {
typeset words IFS v i=0
set -o noglob
set -A words -- $1; shift
for v do
eval "$v=\${words[i]}"
((i += 1))
done
}
split_into "$var" A B C
^IFS 空白字符,每个 POSIX 是在语言环境中分类的字符[:space:]
,并且恰好$IFS
在 ksh88(POSIX 规范所基于的)和大多数 shell 中,这仍然限于 SPC、TAB 和 NL。我发现在这方面唯一符合 POSIX 标准的 shell 是yash
.ksh93
并且bash
(自 5.0 起)还包括其他空格(例如 CR、FF、VT...),但仅限于单字节空格(请注意某些系统(如 Solaris),其中包括单字节的不间断空格在某些地区)