Как удалить \ r \ n в строке и сделать строку в массив - PullRequest
0 голосов
/ 13 марта 2020

У меня есть строка получить из API, как показано ниже

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

Как разделить / patha / pathb / path c на элемент в массиве?

Ответы [ 4 ]

2 голосов
/ 13 марта 2020
$ 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
1 голос
/ 13 марта 2020

Вы можете использовать your_array=($(sed 's/\\r\\n/ /g' <<< $your_string)).

Вы также можете использовать echo $your string | sed. . . ., если хотите. Либо работает нормально. эхо, вероятно, более читабельно и более везде реализовано.

Редактировать: если эти пути содержат пробел, это будет лучший вариант -

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
0 голосов
/ 14 марта 2020

Вы можете создать массив с 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

Повторите попытку после удаления \r из локального IFS, чтобы увидеть разницу.

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

printf "%s" ${arr[0]} | hexdump -C
00000000  61 0d                                             |a.|
00000002
0 голосов
/ 13 марта 2020
:>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

...