Ниже приведен перевод на родной Баш, ни с одной из ошибок, связанных с злоупотребляя AWK, как вы (вспомните, что случилось бы с входного файла с именем EVIL'$(rm -rf .)'.txt
- как созданные с помощью команды touch $'EVIL\'$(rm -rf .)\'.txt'
):
#!/bin/bash
stock=HD
while IFS= read -r line; do
[[ $line = *Rank* ]] || continue
read -r _ _ _ rank _ <<<"$line"
case $rank in
1-Strong) mv -- "$stock.txt" ~/Desktop/Stocks/1/ ;;
2-Buy) mv -- "$stock.txt" ~/Desktop/Stocks/2/ ;;
3-Hold) mv -- "$stock.txt" ~/Desktop/Stocks/3/ ;;
4-Sell) mv -- "$stock.txt" ~/Desktop/Stocks/4/ ;;
5-Strong) mv -- "$stock.txt" ~/Desktop/Stocks/5/ ;;
esac
done <"$stock.txt"
Однако, это не имеет особого смысла, так как это написано: вы работаете один mv
в каждой строке в файле сопоставления Rank
- но вы не можете успешно переместить один файл несколько раз. Возможно, вы просто хотите прочитать строку , первую строку, содержащую Rank
, и переименовать файл в соответствии с номером, предшествующим тире в четвертом столбце?
#!/bin/bash
stock=HD
if read -r _ _ _ rating _ < <(grep -e Rank "$stock.txt") && [[ $rating ]]; then
mv -- "$stock.txt" ~/Desktop/Stocks/"${rating%%-*}"/
fi
Объяснение:
<(...)
заменяется именем файла, который при чтении, возвращает вывод команды прилагается. Таким образом, foo < <(...)
запускает foo
в родительской оболочке со своим stdin, поданным из команды в ...
. См. BashFAQ #24, чтобы понять, почему это необходимо, а не работает grep -e Rank "$stock.txt" | read _ _ _ rating _
.
read _ _ _ rating _
читает четвертое слово своего входного потока в переменную rating
. (Первая, вторая, третья и пятая и нижняя часть считываются в переменные с именем _
, что является соглашением для чего-то, чего вас не волнует или хочет выбросить).
"${rating%%-*}"
выбрасывает все содержимое в переменной rating
следующие первой -
, таким образом, преобразование 1-Strong
к 1
, 2-Buy
к 2
и т.д.
Тем не менее, все вышесказанное не объясняет точную ошибку вы получаете. Для того, чтобы получить, что, давайте сломаем ваши awk
команды:
system("mv " "'$stock'.txt" " " ~/Desktop/Stocks/1/"'$stock'.txt") ;
... так, какие строки объединяются вместе и передаются system()
(и, таким образом, /bin/sh
)?
system(
"mv "
"'$stock'.txt"
" "
~/Desktop/Stocks/1/"'$stock'.txt"
) ;
Уточнить проблему здесь? Эта четвертая часть (которую вы собираетесь объединить вместе с остальными) не является строкой в awk! Таким образом, когда он содержит операции , их обрабатывают как числовое деление - литье содержимого до него до числового значения и деление на содержимое после него (аналогично, отличное от целого). В некоторых awk-версиях, включая мои, это приводит к ошибке с делением на нуль; ваш, очевидно, отличается.
(Также $stock
является буквальным строки, а не замещен HD
здесь, но это отдельная тема)
Вы пытались использовать '#!/usr/bin/env bash'? Может быть, bash не там, где вы думаете. Использование этой формы линии she-bang переносимо и применяется ко всем системам * nix. Однако '#!/Bin/bash' не является. Также, когда вы используете bash из терминала, вы используете 'sh' или' bash'? Существует разница, которую вы используете. – rbaleksandar
Вы найдете кодирование намного проще, если вы напишете его в крошечных битах и протестируете каждую модификацию вместо написания полного скрипта, а затем попытаетесь устранить ее. –
EW. Использование 'system()' таким образом открывает вам серьезные уязвимости безопасности. –