Итак, у меня есть файл с содержимым, которое нужно использовать, и некоторые входные параметры в заголовке файла. Я хотел бы изменить входные данные, но сохранить содержимое прежним. Я также называю файлы на основе какой ввод используется. Например, скажем, у меня есть имя файла:
input1-input2-input3
Я хотел бы скопировать этот файл и изменить input3 на input4 или что-то в этом роде, и я хочу, чтобы имя отражало это. У меня есть пытался написать простой сценарий bash, который выглядит следующим образом:
#!/bin/bash
#Inputs:{file to be copied} {solvent to change}
file=${1?No file given}
input3=${2?no input}
внесите некоторые изменения
cp file newfile
Интернет дал мне несколько советов по "внесению некоторых изменений", например е этот совет: http://www.peteryu.ca/tutorials/shellscripting/batch_rename так что моя текущая попытка выглядит так с именем файла
#!/bin/bash
#Inputs:{file to be copied} {solvent to change}
file=${1?No file given}
solvent=${2?no solvent given}
filename=$(basename "$file" .gjf) ls -1 $file | awk '{print("mv "$1 "" $1)}' | sed "s/solvent/$solvent/2" > rename_"$filename".txt
newfile=awk '{print $3}' rename_"$filename".txt
if [ -f "$newfile" ]
then
echo "$newfile" > "$dir/newfile"
fi
cp "$file" "$newfile"
~
У меня это не сработало, потому что я думаю, что эта ссылка отвечает на другой вопрос.
Итак, у меня есть файл под названием:
input1-input2-input3
Я хотел бы написать сценарий bash, который будет выглядеть так:
.\bash.bash input1-input2-input3 input4
с выводом:
input1-input2-input4
Теоретически я хотел бы изменить все эти поля в будущем, но пока я хотел бы просто упростить пример.
]Спасибо вам всем! Это мой первый пост, поэтому дайте мне знать, если у меня возникнут проблемы с форматированием
Привет, Герман Барсенас :) Мы подготовили небольшой скрипт, который делает то, что вы просите в конце вопроса:
#!/bin/bash
# Get the input parameters
old_file=${1?No file given}
solvent=${2?no solvent given}
# Get the basename of the file
old_file_base=$(basename $old_file '.gjf')
# Run it through awk
new_file=$(echo $old_file_base | awk -v sol=$solvent '{split($0, tmp, "-"); \
tmp[3] = sol; print sprintf("%s-%s-%s", tmp[1], tmp[2], tmp[3])}')
# It can all be compressed into one line
# new_file=$(basename $old_file '.gjf' | awk -v sol=$solvent '{split($0, foo, "-"); \
# foo[3] = sol; print sprintf("%s-%s-%s", foo[1], foo[2], foo[3])}')
# Work with the file...
# Uncomment to check the new filename is correct
echo $new_file
# And copy the file
# cp $old_file $new_file
Мы пробовали скрипт на bash 3.2.57
, и он должен работать как есть. Он просто выводит имя файла, которое будет добавлено к вновь скопированному файлу, но вы можете настроить его по своему усмотрению. Давайте посмотрим на каждый кусок.
old_file=${1?No file given}
solvent=${2?no solvent given}
Эта часть скопирована из вашего примера, поэтому мы не будем вдаваться в подробности. Мы просто хотим указать, что мы изменили имя первого входного параметра, чтобы сделать его более понятным.
old_file_base=$(basename $old_file '.gjf')
Эта часть сохранит базовое имя файла в переменной old_file_base
. Этот дополнительный шаг не нужен, но мы добавили его, чтобы попытаться сделать все более понятным. Мы запускаем эту команду, чтобы скрипт работал, даже если предоставленный путь к файлу является абсолютным (т. е. он указан из корневой папки, поэтому он начинается с /
. Примером абсолютного пути является / абсолютный/путь/к/foo
).
awk
new_file=$(echo $old_file_base | awk -v sol=$solvent '{split($0, tmp, "-"); \
tmp[3] = sol; print sprintf("%s-%s-%s", tmp[1], tmp[2], tmp[3])}')
Вот где лежит "сердце" программы. Мы начнем с использования echo
для вывода содержимого old_file_name
в STDOUT, а затем с помощью канала (|
) для перенаправления echo
STDOUT на awk
в STDIN. Таким образом, awk
будет работать с базовым именем, которое мы получили на предыдущем шаге.
Обратите внимание, что мы используем опцию -v
при вызове awk
.Мы делаем это для «передачи» внешних переменных в awk
, чтобы их можно было использовать при обработке ввода. С помощью -v sol=$solvent
мы можем ссылаться на sol
внутри awk
, и его значение будет значением переменной solvent
в скрипте. (т.е. второй параметр, передаваемый при запуске скрипта). Затем мы находим awk
"сценарий" между фигурными скобками. Он содержит 3 отдельные инструкции:
a) split($0, tmp, "-")
: функция split()
примет весь ввод ($0
внутри awk
) и разделить его на символы -
. Результаты будут возвращены в массиве tmp
.
b) tmp[3] = sol
: мы просто присвоим sol
третьему элементу. Обратите внимание, что awk
начинает индексацию с 1, а не с 0! Мы жестко кодируем индекс, потому что знаем формат имени входного файла. В противном случае вам может потребоваться быть осторожным и проверить размер массива вручную.
c) print sprintf("%s-%s-%s", tmp[1], tmp[2], tmp[3])
: sprintf()
функция «вернет» строку, которую мы получим, назначив переданные значения заполнителям, определенным знаком процента (%
). Как и в C, %s
— это заполнитель для строки. В этом случае sprintf()
вернет три элемента массива tmp
, соединенные дефисами (-
) в виде строки.Поскольку ранее мы изменили значение tmp[3]
на желаемый результат, результат будет таким, каким мы его ожидаем. Затем мы вызываем print
для вывода этой строки в STDOUT. Поскольку вся эта команда находится в структуре подстановки команд (например, $()
), содержимое, выводимое в STDOUT, будет присвоено переменной new_file
.
Тогда у нас есть желаемый результат! Вы можете проверить это, запустив echo $new_file
и проверив вывод вашего терминала. Если вы передадите 3-й параметр в командной строке, чтобы контролировать, какой ввод следует изменить в имени файла, вы можете просто передать его в awk
через параметр -v
и обработать имя так, как вы хотите. внутри самого awk
.
Вот некоторые результаты, которые мы получили на нашей машине:
bash-3.2$ ./foo.sh input1-input2-input3 input-5
input1-input2-input-5
bash-3.2$ ./foo.sh input1-input2-input3 input-4
input1-input2-input-4
Мы назвали наш скрипт foo.sh
, у нас плохо с именами :P
Я надеюсь, что этот скрипт поможет вам в любом случае. Если я каким-то образом неправильно понял ваш вопрос или вам нужны дополнительные указания, сообщите мне, чтобы я мог помочь :)