等于换行符的IFS在bash中不起作用

时间:2018-12-03 05:48:22

标签: bash ifs

我有一个多行字符串,我想基于SELECT c.* , TIMESTAMPDIFF(MONTH,'2018-11-30 09:18:23',c.end_time) diff_month1 , case when TIMESTAMPDIFF(MONTH,'2018-11-30 09:18:23',c.end_time) = 0 then 'equal' when TIMESTAMPDIFF(MONTH,'2018-11-30 09:18:23',c.end_time) > 0 then 'greater' end diff_month , TIMESTAMPDIFF(MINUTE,'2018-11-30 09:18:23',c.end_time) diff_minute1 , case when TIMESTAMPDIFF(MINUTE,'2018-11-30 09:18:23',c.end_time) = 0 then 'equal' when TIMESTAMPDIFF(MINUTE,'2018-11-30 09:18:23',c.end_time) > 0 then 'greater' end diff_minute FROM contract c JOIN employee_detail e ON c.emp_id = e.id where TIMESTAMPDIFF(MINUTE,'2018-11-30 09:18:23',c.end_time) = 0 and TIMESTAMPDIFF(MONTH ,'2018-11-30 09:18:23',c.end_time) = 0 进行拆分,为此我设置了\n,但它不起作用,我也尝试过IFS=$'\n'和{{ 1}},但没有运气。 下面是示例代码

IFS=

我正在使用IFS=" ",bash版本为

IFS=$'\n' read -ra arr <<< "line1\nline2\nline3"
printf "%s\n" "${arr[@]}"
# it only generates array of length 1

有人可以指出明显之处吗?

2 个答案:

答案 0 :(得分:1)

从bash手册的bash内置部分:

  

阅读

read [-ers] [-a aname] [-d delim] [-i text] [-n nchars]
    [-N nchars] [-p prompt] [-t timeout] [-u fd] [name …]

One line is read from the standard input, or from the file descriptor fd supplied as an argument to the -u option, 

和行定界符可以用-d

指定
  

-d delim

The first character of delim is used to terminate the input line, rather than newline.

请注意,后跟一个空参数-d '',行定界符将为nul字符,如果输入中没有nul字符,则可用于读取整个输入。

即使在-r模式下,读取速度仍然很慢。

对于较大的输入,更快的解决方案是使用分词:

input=$'line1\nline2\nline3'
IFS=$'\n';set -f;arr=($input);set +f;IFS=$' \t\n'

请注意set -f,以避免全局匹配阶段。

答案 1 :(得分:1)

您尝试的主要问题是分词未使用 herestring 执行。来自男子猛击:

Here Strings
   A variant of here documents, the format is:

          <<<word

   ... Pathname expansion and word splitting are not performed.
   The result is supplied as a single string to the command on its 
   standard input.

Bash确实提供了 heredoc (例如,man bash中的“此处文档”),在其上将使用默认的IFS执行分词。但是,即使那样,您仍将读取文字'\n'作为数组内容的一部分。不用担心,bash提供了一种特定的方式,可以通过将-t(a / k / a readarray)的mapfile选项避免这种情况。

与我最初尝试的最接近的例子是:

readarray -t arr << EOF
line1
line2
line3
EOF
declare -p arr

这会导致您的行按需要保存,例如输出为:

declare -a arr='([0]="line1" [1]="line2" [2]="line3")'

另一种选择是使用进程替换,并让printf提供拆分,例如

readarray -t arr < <(printf "line1\nline2\nline3\n")

填充不包含换行符的数组的关键是readarray -t,允许进行单词拆分的关键是避免使用 herestring