Утсав дал вам правильное решение. Проблема заключалась в том, что вы присваивали значение переменной с именем echo
.
Тем не менее, я дам еще несколько советов по улучшению вашего скрипта.
В настоящее время вы не можете выбрать папку с именем 1
. Кроме того, сценарий излишне интерактивен и вообще не взаимодействует с пользователем. Если бы пользователь, например, указал имя папки в командной строке при вызове сценария, вам вообще не пришлось бы запрашивать имя папки. Только когда пользователь не указал имя папки, вам нужно будет использовать текущий рабочий каталог:
#!/bin/sh
folder="$1"
if [ -z "$folder" ]; then
printf 'No folder given, using "%s"\n' "$PWD" >&2
folder="$PWD"
fi
Тогда зачем вообще заставлять пользователя вводить имя файла в этой папке? Вы можете попросить их выбрать файл из меню :
.select file in "$folder"/*; do
printf 'Making "%s" executable with "sudo chmod +x"\n' "$file"
sudo chmod +x "$folder/$file"
break
done
Полный скрипт, который будет пропускать меню, если в командной строке был указан действительный файл:
#!/bin/sh
folder="$1"
if [ -z "$folder" ]; then
printf 'No folder given, using "%s"\n' "$PWD" >&2
folder="$PWD"
elif [ -f "$folder" ]; then
# $folder is actually a file, chmod it and we're done
sudo chmod +x "$folder"
exit
fi
if [ ! -d "$folder" ]; then
printf 'No such folder: %s\n' "$folder" 2>&1
exit 1
fi
select file in "$folder"/*; do
printf 'Making "%s" executable with "sudo chmod +x"\n' "$file"
sudo chmod +x "$folder/$file"
break
done
Если этот скрипт называется script.sh
, то его можно будет запустить следующими способами:
$./script.sh # asks for file in current folder
$./script.sh myfolder # asks for file in "myfolder"
$./script.sh myfolder/myfile # quietly chmods "myfolder/myfile"
Довольно короткий awk
один -вкладыш:
$ awk '/^D/ { nr = substr($0,2,7); $0 = sprintf("D%07dACCT_%-10d%s", nr, nr, substr($0,24)) } { print }' file
H20190105
D0012345ACCT_12345 100001072010
D0008912ACCT_8912 450023082005
T0001245678
Код awk
обнаружит строки, которые необходимо изменить, по наличию D
в первой позиции.
Новая строка состоит из sprintf()
из нулевого -заполненного числа после D
, строки ACCT_
, за которой следует то же число снова (теперь не ноль -заполнено ), и, наконец, все, что было в и после позиции 24 в строке.
Печатаются все строки (, измененные, как описано выше, или не измененные вовсе ).
$ awk 'NF>1{$0=sprintf("%sACCT_%-11d%s", substr($0,1,8), substr($0,2,7), substr($0,24))} 1' file
H20190105
D0012345ACCT_12345 100001072010
D0008912ACCT_8912 450023082005
T0001245678
$ perl -pe 's/^(D)(.{7})(.{12})/sprintf("%s%s%s%-7s",$1,$2,"ACCT_",$2+0)/e' input.txt
H20190105
D0012345ACCT_12345 100001072010
D0008912ACCT_8912 450023082005
T0001245678
Здесь используется модификатор Perl e
для оператора s/LHS/RHS/
, так что он выполняет RHS как код perl. $2+0
неявно преобразует $2 из строки, дополненной нулями -, в число, которое автоматически удаляет все начальные нули. Формат sprintf()
гарантирует, что длина поля выходной строки точно такая же, как и входная.
Или для ремонта awk
одного -вкладыша:
$ awk '/^D/{$0=substr($0,1,8)"ACCT_"sprintf("%-7s",substr($0,2,7)+0)" "substr($0,24,length($0))} 1' input.txt
H20190105
D0012345ACCT_12345 100001072010
D0008912ACCT_8912 450023082005
T0001245678
awk
тоже имеет sprintf. IMO, это сложнее читать и понимать, чем версию Perl. YMMV.
Другая awk
версия, похожая на версию perl:
$ awk '
/^D/ {
ac=sprintf("%-7s",substr($0,2,7)+0);
$0=gensub("^(D)(.{7})(.{12})","\\1\\2ACCT_"ac,1)
}
1' input.txt
H20190105
D0012345ACCT_12345 100001072010
D0008912ACCT_8912 450023082005
T0001245678
Если вам не нужно удаление нуля -, это можно сделать с помощьюsed
:
$ sed -E -e 's/^(D)(.{7})(.{12})/\1\2ACCT_\2/' input.txt
H20190105
D0012345ACCT_0012345 100001072010
D0008912ACCT_0008912 450023082005
T0001245678