【问题标题】:Split string using \r\n using IFS in bash在 bash 中使用 IFS 使用 \r\n 拆分字符串
【发布时间】:2017-10-04 02:43:35
【问题描述】:

我想在 bash 中拆分包含 \r\n 的字符串,但回车和 \n 会出现问题。谁能给我提示不同的IFS?我也试过 IFS=' |\' 。

输入:

projects.google.tests.inbox.document_01\r\nprojects.google.tests.inbox.document_02\r\nprojects.google.tests.inbox.global_02

代码:

IFS=$'\r'
inputData="projects.google.tests.inbox.document_01\r\nprojects.google.tests.inbox.document_02\r\nprojects.google.tests.inbox.global_02"
for line1 in ${inputData}; do
    line2=`echo "${line1}"`
    echo ${line2} //Expected one by one entry
done

预期:

projects.google.tests.inbox.document_01
projects.google.tests.inbox.document_02
projects.google.tests.inbox.global_02

【问题讨论】:

标签: bash ifs


【解决方案1】:
inputData=$'projects.google.tests.inbox.document_01\r\nprojects.google.tests.inbox.document_02\r\nprojects.google.tests.inbox.global_02'
while IFS= read -r line; do
  line=${line%$'\r'}
  echo "$line"
done <<<"$inputData"

注意:

  • 字符串定义为string=$'foo\r\n',而不是string="foo\r\n"。后者不会在您的变量中放入实际的 CRLF 序列。有关此语法的说明,请参阅 bash-hackers 维基上的 ANSI C-like strings
  • ${line%$'\r'} 是一个 parameter expansion,如果存在的话,它会从变量 line 的内容末尾去除文字回车。
  • BashFAQ #1 中详细描述了逐行读取输入流(此处使用)的做法。与使用 for 进行迭代不同,它不会尝试将您的数据扩展为 glob。

【讨论】:

  • 很有趣,非常感谢!由于价值来自外部,所以我只需要替换为: inputData="${valueFromExternalSource}" ?
  • @JiteshSojitra,是的——如果外部提供的值包含文字而不是转义序列,那将完美地工作。
  • @JiteshSojitra, ...相比之下,如果传入的字符串包含文字转义序列,则会引发数据的问题。如果是 JSON 字符串,最好使用jq 来解释它;如果它只有 C 风格的 printf 转义,那么您可以使用 printf '%b' 将它们转换为文字,如果这是您的意图。
【解决方案2】:

关注 awk 可以帮助您解决问题。

awk '{gsub(/\\r\\n/,RS)} 1'  Input_file

echo "$var" | awk '{gsub(/\\r\\n/,RS)} 1'

输出如下。

projects.google.tests.inbox.document_01
projects.google.tests.inbox.document_02
projects.google.tests.inbox.global_02

解释: 使用awkgsub 用于全局替换的实用程序,它的方法是gsub(/regex_to_be_subsituted/,variable/new_value,current_line/variable),所以这里我给出@987654327 @(这里要注意的一点我在这里转义\\,这意味着它将把它作为一个文字字符)在当前行中使用RS(记录分隔符,其默认值是新行)。然后1 表示,awk 作用于条件和动作的方法,所以通过提及1 我将条件设置为 TRUE 并且没有给出任何动作,因此将发生当前的默认动作打印。

编辑:您可以使用如下变量。

var="projects.google.tests.inbox.document_01\r\nprojects.google.tests.inbox.document_02\r\nprojects.google.tests.inbox.global_02"
echo "$var" | awk '{gsub(/\\r\\n/,RS)} 1'
projects.google.tests.inbox.document_01
projects.google.tests.inbox.document_02
projects.google.tests.inbox.global_02

【讨论】:

  • 非常感谢,你能用字符串值代替文件来回答吗?
  • @JiteshSojitra,请立即检查我编辑的 OR 解决方案,如果您对此有任何疑问,请告诉我。现在也添加了说明。
  • @RavinderSingh13,请不要鼓励人们echo $var(未引用扩展)。
  • @CharlesDuffy,很抱歉我错过了它,现在已经添加了。谢谢你告诉我。
  • @JiteshSojitra,尽管这样做,你可以用一个 awk 本身来做,试一试,可以将它的输出保存到一个变量中,这里不需要 for 循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多