你好,我试图使用 ksh 脚本读取一行到数组。但是,当字段值中存在逗号时,它的某些值会在相邻数组元素中多次存储。怎么避免这种情况我的分隔符是~
输入
17~4~~~char~Y~\"[_a-zA-Z0-9\.]\+@[a-zA-Z0-9]\+\.[a-z]\{2,\}\"~40~email id
代码
while IFS= read -r line
do
if [ $n != 1 ]; then
IFS="~"
set -A star $line
col_pos=${star[1]}
col_patt=${star[6]}
col_len=${star[7]}
col_file_id=${star[0]}
$行的值
17 4 char Y \"[_a-zA-Z0-9\.]\+@[a-zA-Z0-9]\+\.[a-z]\2\" \"[_a-zA-Z0-9\.]\+@[a-zA-Z0-9]\+\.[a-z]\\\" 40 email id
问题是模式 ("[_a-zA-Z0-9.]+@[a-zA-Z0-9]+.[az]\2") 在读取时重复,但在实际输入文件中模式字段被定义一次。
答案1
在:
set -A star $line
正如$line
未引用的那样,您正在调用 split+glob 运算符。在这里,您确实需要分割部分,但不需要全局部分,因此您应该首先禁用它:
set -o noglob
正如@Isaac正确识别的那样,您这里的问题与通配无关,而是由 ksh (且仅 ksh1)除了通配之外完成的大括号扩展,但在禁用通配时也会被禁用。
set -A array x y z
是将数组设置为整体的 ksh88 / pdksh 方法。较新版本的 ksh(包括 ksh93 和 mksh)已采用 zsh 样式array=(x y z)
。
使用set -A
语法,您需要:
set -A array -- values
(除了在 zsh 中不模拟 ksh 时),否则,如果第一个值以-
或开头,它将无法正常工作+
。
所以:
set -o noglob; IFS='~'
while IFS= read -r line
do
if [ "$n" != 1 ]; then
set -A star -- $line
col_pos=${star[1]}
col_patt=${star[6]}
col_len=${star[7]}
col_file_id=${star[0]}
虽然在这里,我会避免所有这些问题并使用这个标准sh
语法:
while IFS='~' read -r col_file_id col_pos x x x x col_patt col_len x
do
if [ "$n" != 1 ]; then
¹ 除非在 mksh 和某些最新版本的 ksh93 中启用了 POSIX 模式,或者在编译时完全禁用了大括号扩展
答案2
问题:
- 该脚本不完整(缺少完成、缺少 fi 等)。
- 变量应该被引用(默认情况下总是)。
但您的主要问题在于大括号表达式{2,}
,它将在 之前重复字符串并以 结尾,2
并且nothing
在 中扩展时set -A star $line
。
一个未引用的 $line
将进行多次扩展,其中之一是大括号扩展{,}
。
要分割字符串,而不将其不加引号地展开,使用~
作为分隔符并将值放入数组中,这可能有效:
while IFS= read -r onestar; do star+=("$onestar"); done <<<"${line//~/$'\n'}"
假设line
只有一行(不包含换行符),它应该,不应该吗?