在运行bash脚本之前,打开文本文件逐行读取以获取数据

时间:2017-07-24 05:15:11

标签: bash grep

我目前正在开发一个bash脚本,脚本的内容将提示用户输入目录路径,并将目录路径存储在变量中。然后,我将目录路径中的文件复制到我的路径,将文件(.html)转换为(.xls)。之后,我使用mailx命令通过电子邮件发送(.xls)文件。但是,文件可能超过1,并且每周都不会修复。

#!/bin/bash

echo "Enter the path: (e.g. /a/b/c/d/e/f/g/h/i/system_name/24_july/full_file)"
read directory

systemname=$(echo $directory | cut -d'/' -f11) #-f11 indicates 'system_name"
dates=$(echo $directory | cut -d'/' -f12) #-f12 indicates '24_july'

cp $directory/mode1/consolidate_full_file/file.mode1/output_mode1/file.html .
mv file.html MODE1_NAME.xls

cp $directory/mode2/consolidate_full_file/file.mode2/output_mode2/file.html .
mv file.html MODE2_NAME.xls

echo "Sending files of $systemname on $dates" | mailx -s "Test" -a MODE1_NAME.xls -a MODE2_NAME.xls mmaz@hotmail.com

因此,我打算要求用户创建一个文本文件,其中包含system_name,目录路径,本周存在的模式。从该文本文件,我打算从bash脚本打开它并获取所需的所有数据。有可能吗?

这是文本文件blocka.txt的示例:

systemname=blocka

directory=/a/b/c/d/e/f/g/h/i/system_name/24_july/full_file

List of modes:
MODE1_NAME= /a/b/c/d/e/f/g/h/i/system_name/24_july/full_file/mode1/consolidate_full_file/file.mode1/output_mode1/file.html
MODE2_NAME= /a/b/c/d/e/f/g/h/i/system_name/24_july/full_file/mode2/consolidate_full_file/file.mode2/output_mode2/file.html

End of List of modes

我试图找到系统名称和目录的字符串匹配,但是如何识别模式列表之间存在模式:直到模式列表结束。

从blocka.txt,我需要获取所需的数据作为变量,以便我可以减少bash脚本中的硬编码。我有什么方法可以尝试这种方式吗?因为我认为它足够有效,因为任何系统名称都可以通过对文本文件进行makig更改来使用它。

1 个答案:

答案 0 :(得分:0)

最简单的方法是使用source,它基本上运行目标文件,保持变量设置。但是,这是不安全的,允许人们将他们想要的任何代码插入到文件中并让主脚本运行它。

相反,我们可以运行while循环,逐行读取文件,并检查一组if语句。

#!/bin/bash
while IFS= read -r line; do
    #If the current line starts with "systemname=", we assign systemname to the section after the equal sign
    if [[ $line =~ ^systemname= ]]; then systemname=$(echo $line | awk -F "=" '{print $2}'); fi
    if [[ $line =~ ^directory= ]]; then directory=$(echo $line | awk -F "=" '{print $2}'); fi
    #etc...

    #The MODEn_NAME section will take a bit more work, if we're expected to handle an unknown number of inputs.
    if [[ $line =~ ^MODE[0-9]*_NAME= ]]; then
        #The following extracts the number, and saves it to $index
        index=$(echo $line | awk -F "=" '{print $1}' | grep -o '[0-9]\+')
        #Now we insert the text after the equal sign into an array element specified by the number
        modename[$index]=$(echo $line | awk -F "=" '{print $2}')
        #We could have saved some code by simply adding to the next available index,
        #But then if a user entered the same mode number twice, we'd have a duplicate
    fi
done< "blocka.txt"

dates=$(echo $directory | cut -d'/' -f12) #-f12 indicates '24_july

#Since we have an unknown number of modename indexes (and not necessarily in order),
#we will use a for loop to go through them.
for i in "${!modename[*]}"; do 
    filelist="$filelist"" MODE""$i""_NAME.xls"#This will be used at the end
    #Edit: cp "$directory/mode""$i""/consolidate_full_file/file.mode""$i""/output_mode1/file.html" .
    #As far as I can tell, each MODEn_NAME entry contains the full directory of each file. Which means you really don't need the $directory from before.
    cp "$modename$i" .
    mv "file.html" "MODE""$i""_NAME.xls" #See note below
done
echo "Sending files of $systemname on $dates" | mailx -s "Test" -a "$filelist" mmaz@hotmail.com

对于那个移动命令,你真的不需要它;您可以首先使用先前的cp命令复制到该名称。但我把它包括在内以说明我做了什么,但没有改变。