0

我正在创建一个 bash 脚本来逐行读取文件,稍后将其格式化为按名称组织,然后按日期组织。我看不出为什么这段代码此时不起作用,尽管我已经尝试使用目录查找器和导出命令自行使用输入和输出文件名变量,但没有出现错误。

export inputfilename="employees.txt"
export outputfilename="branch.txt"
directoryinput=$(find -name $inputfilename)
directoryoutput=$(find -name $outputfilename)
n=1

if [[ -f "$directoryinput" ]]; then
     while read line; do
         echo "$line"
         n=$((n+1))
     done < "$directoryoutput"
 else
    echo "Input file does not exist. Please create a employees.txt file"
 fi

非常感谢所有帮助,谢谢!注意:正如人们注意到的那样,我忘记在将数据传输到文件时添加 $ 符号,但这只是在复制我的代码时,我的实际应用程序中确实有 $ 符号,但仍然没有结果

4

1 回答 1

1

使用 Bash 逐行读取文件

逐行读取文件的最佳和惯用方法是:

while IFS= read -r line; do
  // parse line
  printf "%s" "$line"
done < "file"

有关此主题的更多信息,请参见bashfaq

但是不要逐行读取 bash 中的文件。您可以(好吧,几乎)总是不能在 bash 中逐行读取流。在 bash 中逐行读取文件非常慢,不应该这样做。对于简单的情况,所有的unix工具都可以借助xargsorparallel来使用,对于更复杂的情况awkdatamesh都可以使用。

done < "directoryoutput"

该代码不起作用,因为您正在将名为directoryoutput. 由于这样的文件不存在,您的脚本将失败。

directoryoutput=$(find -name $outputfilename)

可以使用 HERE 字符串构造简单地将带有换行符的变量值附加到 read while 循环中:

done <<< "$directoryoutput"

directoryinput=$(find -name $inputfilename)
if [[ -f "$directoryinput" ]]

只要$inputfilename您的目录中只有一个文件,就可以了。此外,查找文件然后检查它的存在是没有意义的。如果文件更多, find 返回一个换行符分隔的名称列表。但是,我认为小支票if [ "$(printf "$directoryinput" | wc -l)" -eq 1 ]或使用find -name $inputfilename | head -n1会更好。

while read line;
   do
      echo "$line"
      n=$((n+1))
  done < "directoryoutput"

这里的意图很清楚。这只是:

 n=$(<directoryoutput wc -l)
 cat "directoryoutput"

除了while read line删除尾随和前导换行符并且依赖于 IFS。

除非您有理由不这样做,否则请始终记住引用您的变量。

看看shellcheck,它可以找到脚本中最常见的错误。

我会更像这样:

inputfilename="employees.txt"
outputfilename="branch.txt"

directoryinput=$(find . -name "$inputfilename")
directoryinput_cnt=$(printf "%s\n" "$directoryinput" | wc -l)
if [ "$directoryinput_cnt" -eq 0 ]; then
   echo "Input file does not exist. Please create a '$inputfilename' file" >&2
   exit 1
elif [ "$directoryinput_cnt" -gt 1 ]; then
   echo "Multiple file named '$inputfilename' exists in the current path" >&2
   exit 1
fi

directoryoutput=$(find . -name "$outputfilename")
directoryoutput_cnt=$(printf "%s\n" "$directoryoutput" | wc -l)

if [ "$directoryoutput_cnt" -eq 0 ]; then 
    echo "Input file does not exist. Please create a '$outputfilename' file" >&2
    exit 1
elif [ "$directoryoutput_cnt" -gt 1 ]; then 
   echo "Multiple file named '$outputfilename' exists in the current path" >&2
    exit 1
fi

cat "$directoryoutput"
n=$(<"$directoryoutput" wc -l)
于 2018-11-19T20:21:23.137 回答