【问题标题】:How to remove \r\n in string and make string to array如何删除字符串中的 \r\n 并将字符串转换为数组
【发布时间】:2020-06-25 03:12:56
【问题描述】:

我从下面的 api 获取字符串

/patha/pathb/pathc\r\n/patha/pathb/pathc\r\n/patha/pathb/pathc

如何将 /patha/pathb/pathc 拆分为数组中的元素?

【问题讨论】:

  • 在 SO 上,我们确实鼓励用户添加他们为解决自己的问题而付出的努力;所以请添加相同的内容,然后让我们知道。

标签: bash awk sed tr


【解决方案1】:

您可以使用your_array=($(sed 's/\\r\\n/ /g' <<< $your_string))

如果您愿意,也可以使用echo $your string | sed. . . .。要么工作正常。 echo 可能在任何地方都更具可读性和更多实现。

编辑:如果这些路径包含空格,这将是一个更好的选择 -

your_array=($(sed 's/ /~_~/g; s/\\r\\n/ /g' <<< $your_string))
i=0
for x in ${your_array[@]}; do your_array[$i]=$(sed 's/~_~/ /g' <<< $x) && let i++; done

我使用~_~ 不覆盖任何现有字符。

Edit2:这是一个更好的方法 -

temp=$(sed 's|\\r||g; s|\\|\\\\|g' <<< $your_string)
ifs=$IFS
IFS="
"
your_array=($(for x in $(eval echo -e $temp); do echo $x; done))
IFS=$ifs

【讨论】:

  • 我认为对于这项任务,your_array=($(dos2unix &lt;&lt;&lt;$your_string)) 会更清晰,但如果其中一个路径组件嵌入了空格,这两种解决方案都会中断,因为分词会发生在空格和换行符上。
  • @user1934428 我已经更新了答案。虽然,这似乎有点乏味。我愿意接受其他想法。
  • 我认为第二种方法更好。如果路径已经包含~_~,第一个会失败。至于另一个想法,看看anubhava对this问题的回复。虽然我无法让它工作,可能是因为我正在取消 Cygwin 环境,但这种方法看起来很有希望。
  • @user1934428 我也认为第二个更有希望。关于您链接到的另一个答案,问题是它们具有特定的分隔符,这也不是大多数实用程序认为的特殊字符。此外,由于文件/目录名称的随机性,他们可以使用正则表达式进行内部搜索,而我们不能。
  • 除了空白问题之外,由于您要求外壳程序通过删除标准双引号来解释它应该默认情况下出现在所有变量扩展周围。见mywiki.wooledge.org/Quotes。第二个脚本还将删除作为文件名一部分的任何\rs,而不仅仅是每个文件名末尾的那些(在\r\n 的上下文中),并且我怀疑它会使您暴露于恶意代码执行礼貌eval.
【解决方案2】:
:>arr=$(echo "/patha/pathb/pathc\r\n/patha/pathb/pathc\r\n/patha/pathb/pathc" | tr '\\r\\n' '\n'  | grep -v '^$')
:>for i in $arr
> do
> echo $i
> done
/patha/pathb/pathc
/patha/pathb/pathc
/patha/pathb/pathc
:>

使用tr

【讨论】:

  • 这种方法行不通。 tr 将其参数视为单个字符,而不是字符串。每次都会给他带来无法预料的结果。
  • 如果路径包含空格或通配符也会失败。
  • @anotherusername 您能否提供一个示例。道歉,但我没有明白这一点
  • @DigvijayS 例如 - echo 'this is a line\nthis is another line' | tr '\\n' ' ' 的输出不会是“这是一行这是另一行”。它将是“这是一个谎言,这是另一个谎言”。
【解决方案3】:
$ str='/patha/pathb/pathc\r\n/patha/pathb/pathc\r\n/patha/pathb/pathc'
$ readarray -t -d $'\n' arr < <(sed 's/\\r\\n/\n/g' <<< "$str")
$ declare -p arr
declare -a arr=([0]="/patha/pathb/pathc" [1]="/patha/pathb/pathc" [2]="/patha/pathb/pathc")

以上内容适用于任何 str 的值,路径中的换行符除外 - 如果这对您来说是个问题,请弄清楚如何使用 \0 (NUL) 而不是 \n 作为路径分隔符。

不知道为什么我无法使用 NUL 作为分隔符:

$ readarray -t -d $'\0' arr < <(sed 's/\\r\\n/\0/g' <<< "$str")
$ declare -p arr
declare -a arr=([0]=$'/patha/pathb/pathc\\r\\n/patha/pathb/pathc\\r\\n/patha/pathb/pathc\n')

这些的一些变体也不起作用,所以我可以避免调用 sed:

$ echo "${str//\\r\\n/\n}"
/patha/pathb/pathcn/patha/pathb/pathcn/patha/pathb/pathc

$ echo "${str//\\r\\n/"$'\n'"}"
/patha/pathb/pathc$'\n'/patha/pathb/pathc$'\n'/patha/pathb/pathc

$ echo "${str//\\r\\n/"$(printf $'\n')"}"
/patha/pathb/pathc/patha/pathb/pathc/patha/pathb/pathc

【讨论】:

  • 也许将--null-data 添加到sed 会有所帮助?
  • @user1934428 不,它没有。
【解决方案4】:

您可以使用本地范围的 IFS 创建一个数组。

my_str=$'a\r\nb\r\nc\r\n'
IFS=$'\r\n' arr=($(echo "$my_str"))

printf "%s" ${arr[0]} | hexdump -C
00000000  61                                                |a|
00000001

从本地 IFS 中删除 \r 后重试以查看差异。

IFS=$'\n' arr=($(echo "$my_str"))

printf "%s" ${arr[0]} | hexdump -C
00000000  61 0d                                             |a.|
00000002

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 2018-07-24
    相关资源
    最近更新 更多