我设法编写了以下脚本:
#!/bin/bash
#files list
file1=/tmp/1wall_long.txt
file2=/tmp/1wall_test1.txt
file3=/tmp/1wall_test2.txt
file4=/tmp/1wall_test3.txt
file5=/tmp/3mt_long.txt
file6=/tmp/3mt_OpenSpace_test1.txt
file7=/tmp/3mt_OpenSpace_test2.txt
file8=/tmp/3mt_OpenSpace_test3.txt
file9=/tmp/3rooms_test1.txt
file10=/tmp/3rooms_test2.txt
file11=/tmp/3rooms_test3.txt
file12=/tmp/20mt_OpenSpace_test1.txt
file13=/tmp/20mt_OpenSpace_test2.txt
file14=/tmp/20mt_OpenSpace_test3.txt
#script for 1wall_long file
if [ ! -e "$file1" ]; then #check if the file exist
echo "File 1wall_long.txt does not exist" #if not exist print echo output
else
sed -i -e 's/- /-/g' $file1 #remove space on the first 10 values
awk '{print $7}' $file1 > /tmp/1wall_long_S.txt #print the column number 7 and copy the output in a file
rm $file1 #remove old file
fi
对变量中描述的所有文件重复该脚本(基本上我使用不同的变量重复相同的脚本 14 次)是否有更好的方法来做到这一点以及这些情况下的最佳实践是什么?
答案1
无循环的
首先使用一个函数
function sevenc
{
if [ ! -e "$1" ]; then #check if the file exist
echo "File $1 does not exist" #if not exist print echo output
else
sed -i -e 's/- /-/g' "$1" #remove space on the first 10 values
awk '{print $7}' "$1" > /tmp/$(basename $1.txt)_S.txt #print the column number 7 and copy the output in a file
rm "$1" #remove old file
fi
}
- 当 shell 识别一个函数时,它将传递参数(如果有的话,传递给 $1 $2 ...等等)。
- 顺便一提
's/- /-/g' "$1" #删除前 10 个值上的空格
不,它会全部转到space-线上-,无论是 1、4、10 还是 255。
那么不需要更多的var
sevenc /tmp/1wall_long.txt
sevenc /tmp/1wall_test1.txt
sevenc /tmp/1wall_test2.txt
sevenc /tmp/1wall_test3.txt
sevenc /tmp/3mt_long.txt
sevenc /tmp/3mt_OpenSpace_test1.txt
sevenc /tmp/3mt_OpenSpace_test2.txt
sevenc /tmp/3mt_OpenSpace_test3.txt
sevenc /tmp/3rooms_test1.txt
sevenc /tmp/3rooms_test2.txt
sevenc /tmp/3rooms_test3.txt
sevenc /tmp/20mt_OpenSpace_test1.txt
sevenc /tmp/20mt_OpenSpace_test2.txt
sevenc /tmp/20mt_OpenSpace_test3.txt
(前提是您不再使用 fileXX var)。
无循环(解决方案 2)
如果你想传递更多参数,并使用 Terdon 的优化尝试
function eight
{
file=$1
destdir=${2-/tmp} # use second arg if defined, else /tmp
exten=${3-S}
if [ ! -e "$file" ]; then #check if the file exist
echo "File $file does not exist" #if not exist print echo output
else
sed -e 's/- /-/g' "$file" \
awk '{print $7}' "$1" > /"$destdir"/$(basename $1.txt)_"$exten".txt #print the column number 7 and copy the output in a file
rm "$file" #remove old file
fi
}
被称为与
eight /tmp/1wall_test3.txt /my/projec/dir T ## will use /my/project/dir as dit, T as extension
eight /tmp/1wall_test1.txt /my/project ## will use /my/project as dir
eignt /tmp/1wall_test2.txt ## will use default value
这些函数可以在 .bashrc 中定义并交互使用。
带循环
while read f
do
if [ ! -e "$f" ]; then #check if the file exist
echo "File $1 does not exist" #if not exist print echo output
else
sed -i -e 's/- /-/g' "$f" #remove space on the first 10 values
awk '{print $7}' "$f" > "/tmp/$(basename $f .txt)_S.txt" #print the column number 7 and copy the output in a file
rm "$f" #remove old file
fi
done <<EOF
/tmp/1wall_long.txt
/tmp/1wall_test1.txt
/tmp/1wall_test2.txt
/tmp/1wall_test3.txt
/tmp/3mt_long.txt
/tmp/3mt_OpenSpace_test1.txt
/tmp/3mt_OpenSpace_test2.txt
/tmp/3mt_OpenSpace_test3.txt
/tmp/3rooms_test1.txt
/tmp/3rooms_test2.txt
/tmp/3rooms_test3.txt
/tmp/20mt_OpenSpace_test1.txt
/tmp/20mt_OpenSpace_test2.txt
/tmp/20mt_OpenSpace_test3.txt
EOF
答案2
就我个人而言,我会避免对文件名进行硬编码。这很少是一个好主意,通常最好选择将目标文件作为参数传递。此外,您正在就地修改文件,然后删除原始文件。这效率不高,只需动态修改文件并打印第七列,而无需将其写入磁盘。例如:
#!/usr/bin/env bash
## Iterate over the file names given
for file in "$@"; do
## Get the output file's name. The ${file%.*} is
## the file's anme without its extension.
outfile="${file%.*}"_S.txt
## If the file exists
if [ -e "$file" ]; then
## remove the spaces and print the 7th column
sed 's/- /-/g' "$file" | awk '{print $7}' > "$outfile" &&
## Delete the original but only if the step
## above was successful (that's what the && does)/
rm "$file"
else
## If the file doesn't exist, print an error message
echo "The file $file does not exist!"
fi
done
然后,您可以像这样运行脚本:
foo.sh /tmp/1wall_long.txt /tmp/1wall_test1.txt /tmp/1wall_test2.txt /tmp/1wall_test3.txt /tmp/20mt_OpenSpace_test1.txt /tmp/20mt_OpenSpace_test2.txt /tmp/20mt_OpenSpace_test3.txt /tmp/3mt_long.txt /tmp/3mt_OpenSpace_test1.txt /tmp/3mt_OpenSpace_test2.txt /tmp/3mt_OpenSpace_test3.txt /tmp/3rooms_test1.txt /tmp/3rooms_test2.txt /tmp/3rooms_test3.txt
如果您确实想要对名称进行硬编码,只需使用 @choroba 建议的数组:
#!/usr/bin/env bash
files=(/tmp/1wall_long.txt /tmp/1wall_test1.txt /tmp/1wall_test2.txt /tmp/1wall_test3.txt /tmp/20mt_OpenSpace_test1.txt /tmp/20mt_OpenSpace_test2.txt /tmp/20mt_OpenSpace_test3.txt /tmp/3mt_long.txt /tmp/3mt_OpenSpace_test1.txt /tmp/3mt_OpenSpace_test2.txt /tmp/3mt_OpenSpace_test3.txt /tmp/3rooms_test1.txt /tmp/3rooms_test2.txt /tmp/3rooms_test3.txt )
## Iterate over the file names given
for file in "${files[@]}"; do
## Get the output file's name. The ${file%.*} is
## the file's anme without its extension.
outfile="${file%.*}"_S.txt
## If the file exists
if [ -e "$file" ]; then
## remove the spaces and print the 7th column
sed 's/- /-/g' "$file" | awk '{print $7}' > "$outfile" &&
## Delete the original but only if the step
## above was successful (that's what the && does)/
rm "$file"
else
## If the file doesn't exist, print an error message
echo "The file $file does not exist!"
fi
done
答案3
您可以使用文件数组并使用以下命令循环它for
:
#!/bin/bash
files=(/tmp/1wall_long.txt
/tmp/1wall_test1.txt
/tmp/1wall_test2.txt
/tmp/1wall_test3.txt
/tmp/3mt_long.txt
/tmp/3mt_OpenSpace_test1.txt
/tmp/3mt_OpenSpace_test2.txt
/tmp/3mt_OpenSpace_test3.txt
/tmp/3rooms_test1.txt
/tmp/3rooms_test2.txt
/tmp/3rooms_test3.txt
/tmp/20mt_OpenSpace_test1.txt
/tmp/20mt_OpenSpace_test2.txt
/tmp/20mt_OpenSpace_test3.txt )
for file in "${files[@]}" ; do
if [ ! -e "$file" ]; then
echo "File $file does not exist"
else
sed -i -e 's/- /-/g' "$file"
# Use parameter expansion to create the new file name.
newfile=${file%.txt}_S.txt
awk '{print $7}' "$file" > "$newfile"
rm "$file"
fi
done