我一直在试图解决这个问题,不幸的是我不能。 我正在尝试创建一个函数,该函数可以找到";"字符,在它之前放置四个空格,然后将代码重新组合在一个整洁的句子中。 我已经破解了一段时间,但无法弄清楚一些事情。 我无法让输出显示我想要的内容。 我尝试查找";"字符的索引,但似乎我以错误的方式处理它。 我似乎犯的另一个错误是,我试图在 for 循环中拆分数组,然后按字母拆分数组中的各个单词,但我也不知道该怎么做。 如果有人能给我一个指针,这将不胜感激。这是在 bash 版本 4.3.48 中
#!commentPlacer()
{
arg=($1) #argument
len=${#arg[@]} #length of the argument
comment=; #character to look for in second loop
commaIndex=(${arg[@]#;}) #the attempted index look up
commentSpace=" ;" #the variable being concatenated into the array
for(( count1=0; count1 <= ${#arg[@]}; count1++ )) #search the argument looking for comment space
do if [[ ${arg[count1]} != commentSpace ]] #if no commentSpace variable then
then for (( count2=0; count2 < ${#arg[count1]} ; count2++ )) #loop through again
do if [[ ${arg[count2]} != comment ]] #if no comment
then A=(${arg[@]:0:commaIndex})
A+=(commentSpace)
A+=(${arg[@]commaIndex:-1}) #concatenate array
echo "$A"
fi
done
fi
done
}
如果我正确理解你想要什么,基本上就是在参数中的每个";"前面放 4 个空格,然后打印结果。这实际上很容易在带有字符串替换的 bash 中完成:
commentPlacer() {
echo "${1//;/ ;}"
}
这里的扩展格式为${variable//pattern/replacement}
,它给出了变量的内容,每次出现的pattern
都替换为replacement
。请注意,在模式之前只有一个/
,它将仅替换第一个匹配项。
现在,我不确定我是否理解您的脚本应该如何工作,但我看到一些事情显然没有按照您的期望去做。以下是我看到的问题的快速摘要:
arg=($1) #argument
这不会从第一个参数创建字符数组。var=(...)
将( )
中的事物视为单词列表,而不是字符。由于$1
不在双引号中,因此它将根据空格(通常是空格、制表符和换行符(拆分为单词,然后任何包含通配符的单词都将扩展为匹配文件名的列表。我很确定这根本不是你想要的(事实上,它几乎从来都不是你想要的,所以变量引用几乎总是应该用双引号来防止它(。在 bash 中创建字符数组并不容易,而且通常不是您想要做的事情。您可以使用${var:index:1}
访问字符串变量中的各个字符,其中index
是您想要的字符(从 0 开始计数(。
commaIndex=(${arg[@]#;}) #the attempted index look up
这不会执行查找。替换${var#pattern}
给出var
的值,pattern
从前面删除(如果匹配(。如果有多个可能的匹配项,则使用最短的匹配项。变体${var##pattern}
使用最长的匹配。使用${array[@]#pattern}
,它将尝试从每个元素中删除模式 - 并且由于它不在双引号中,因此其结果像往常一样被单词拆分和通配符扩展。我很确定这根本不是你想要的。
if [[ ${arg[count1]} != commentSpace ]] #if no commentSpace variable then
在这里(以及许多其他地方(,你使用的是前面没有$
的变量;这根本不使用变量,它只是将"commentSpace"视为静态字符串。此外,在一些地方,用双引号括起来很重要,例如,保持$commentSpace
中的空格不会因单词拆分而消失。有些地方可以安全地关闭双引号,但总的来说,很难跟踪它们,所以只需在任何地方使用双引号。
一般建议:不要试图用bash编写C(或Java或其他(程序;它的工作方式太不同了,你必须以不同的方式思考。使用 shellcheck.net 发现常见问题(如非双引号变量引用(。最后,您可以通过将set -x
放在未按预期执行的部分之前来查看 bash 在做什么;这将使 bash 在执行时打印每一行,显示它正在执行的等效内容。
在 stdin(标准(上使用模式替换创建一个小函数:
semicolon4s() { while read x; do echo "${x//;/ ;}"; done; }
semicolon4s <<< 'foo;bar;baz'
输出:
foo ;bar ;baz