测试-gs-xcf-溶剂.gjf

测试-gs-xcf-溶剂.gjf

所以我有一些文件,其中包含要使用的内容和文件标题中的一些输入参数。我想更改输入但保持内容不变。我还根据正在使用的输入来命名文件。例如,假设我有一个文件名:

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 所以我目前的尝试看起来像这样,文件名为

测试-gs-xcf-溶剂.gjf

 #!/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

理论上,我希望将来能够改变所有这些字段,但就目前而言,我只想让示例更简单一些。

谢谢大家!这是我在这里的第一篇文章,所以如果我有任何格式问题,请告诉我

答案1

你好,German Barcenas:)我们准备了一个小脚本,可以按照你在问题末尾的要求执行:

剧本

#!/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,它应该可以按原样运行。它只会输出将添加到新复制的文件的文件名,但您可以根据需要对其进行调整。让我们来看看每一部分。

  1. 输入参数
old_file=${1?No file given} 
solvent=${2?no solvent given}

这部分是从您的示例中复制而来的,因此我们不会详细介绍。我们只想指出,我们更改了第一个输入参数的名称,以尝试使命名更清晰。

  1. 获取基本名称
old_file_base=$(basename $old_file '.gjf')

此部分将文件的基本名称保存到变量中old_file_base。此额外步骤不是必需的,但我们已添加它以尝试使一切更清晰。我们运行此命令以使脚本工作,即使提供的文件路径是绝对路径(即,它是从根文件夹给出的,因此它以 开头/。绝对路径的一个示例是/absolute/path/to/foo)。

  1. 运行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,然后使用管道 ( )将 的 STDOUT|重定向到的 STDIN。这样将根据我们在上一步中获得的基本名称进行操作。echoawkawk

-v请注意,我们在调用时使用了 option awk。我们这样做是为了将外部变量“传递”给,以便awk在处理输入时使用它们。我们可以在 within 中-v sol=$solvent引用,其值将是脚本中变量的值(即运行脚本时传递的第二个参数)。然后我们在花括号之间找到“脚本”。它包含 3 条不同的指令:solawksolventawk

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()的三个元素作为字符串。由于我们之前用所需的输出更改了 的值,因此结果将是我们期望的结果。然后我们调用将该字符串输出到 STDOUT。由于整个命令都在命令替换结构(即)内,因此输出到 STDOUT 的内容将分配给变量。tmp-tmp[3]print$()new_file

然后我们就得到了想要的输出!您可以通过运行echo $new_file并检查终端的输出来检查。如果您在命令行上传递第三个参数来控制在文件名中要更改的输入,您可以直接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

我希望这个脚本能帮到你。如果我误解了你的问题,或者你需要进一步的指导,请告诉我,这样我就可以提供帮助 :)

相关内容