Скрипт Bash, эхо переносится, когда я этого не хочу - PullRequest
1 голос
/ 16 марта 2019

У меня есть скрипт bash, обертывающий пару curl s, переданных через некоторые другие встроенные функции. Я хочу напечатать результат каждого скручивания, а затем проанализировать результаты и выдать третью строку, которая содержит дополнительную информацию. Окончательный результат должен выглядеть следующим образом:

https://e.thingzz.com/eqvjzc23xqo2s
https://e.thingzz.com/o7jlafrot2fok
https://e.thingzz.com/c/eqvjzc23xqo2s/o7jlafrot2fok

Вместо этого это выглядит так:

https://e.thingzz.com/eqvjzc23xqo2s
https://e.thingzz.com/o7jlafrot2fok
/o7jlafrot2fokv.com/c/eqvjzc23xqo2s

По какой-то причине, он переносится на точную длину предыдущих двух строк.

Сценарий:

#!/usr/bin/env bash
function myCurl()
{
    curl ... | ... | ... 
    #omitted, results in printing a url like 'https://e.thingzz.com/UUID' 
}

# param validation omitted
URL1=$(myCurl "${1}")
URL2=$(myCurl "${2}")
# print both URLs
echo $URL1
echo $URL2

# Parse URLs to get ID at end
# I've also tried using `cut`, in case there were invisible characters?
# I don't really know what I'm talking about.
URLID1=$(echo $URL1 | awk -F 'https://thing.com/' '{print $2}')
URLID2=$(echo $URL2 | awk -F 'https://thing.com/' '{print $2}')

# Doesn't work. Looks like:
# /o7jlafrot2fokv.com/c/eqvjzc23xqo2s
echo https://thing.com/c/${URLID1}/${URLID2}
# Proves I can echo something longer
echo doneaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
# Also wraps, exactly like the `echo` version
echo $URLID1 $URLID2 | awk '{ printf "https://thing.com/c/%s/%s", $1, $2 }'

Я далеко не эксперт по bash, и не знаю, что здесь происходит. Я пробовал варианты этого из командной строки (не вызывая сценарий), и это работает. Я действительно просто в растерянности.

РЕДАКТИРОВАТЬ: Я заменил SCANID1 на URLID1 (и для 2 также). Это были ошибки копирования-вставки.

1 Ответ

5 голосов
/ 16 марта 2019

Как уже заметил Джонатан Леффлер в комментарии, наиболее вероятным объяснением является наличие в данных окончания строк Windows (CRLF). Unix использует LF окончания строк. На терминале символ CR перемещает курсор в начало строки, не перемещая его на следующую строку. Например, если вы запустите

printf '%s\r%s\n' wibble foo

вы увидите fooble, поскольку отображается wibble, затем курсор перемещается в начало строки и foo перезаписывает начало wibble.

Ваш скрипт не полностью соответствует вашему примеру вывода, но кажется, что строка

echo https://thing.com/c/${SCANID1}/${SCANID2}

производит вывод с косой чертой и значением SCANID2 в начале строки. Это происходит потому, что значение SCANID1 оканчивается символом CR.

Чтобы сделать ваш скрипт устойчивым к концу строки Windows, удалите любой символ CR или хотя бы любой символ CR в конце строки (если у вас есть символы CR в других местах, у вас есть другие проблемы с вашими данными). В bash "${var%$'\r'}" дает значение var минус конечный CR, если значение заканчивается CR, и дает значение без изменений, если оно не заканчивается CR.

Я рекомендую удалить CR заранее, чтобы избежать проблем:

URL1=$(myCurl "${1}"); URL1=${URL1%$'\r'}
URL2=$(myCurl "${2}"); URL2=${URL2%$'\r'}

(Невозможно объединить подстановку команд и усечение в одном назначении.)

Но вы также можете сделать это на этапе awk:

SCANID1=$(echo "$URL1" | awk -F 'https://thing.com/' '{print sub("\r", "", $2)}')

Имейте в виду, здесь нет необходимости вызывать awk.

SCANID1=${URL1#*https://*/}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...