BASH ERROR: syntax error: operand expected (error token is ")
BASH ERROR: syntax error: operand expected (error token is ")
我是 bash 脚本编写新手,我的一个脚本有问题。在从充满 XML 文件的文件夹中读取他们的生日并计算他们的年龄后,我试图编写一份 25 岁以下司机的列表。一旦我确定他们未满 25 岁,driver 的数据的文件名就会保存到一个文本文件中。该脚本一直运行到某个点,然后停止。我得到的错误是:
gdate: extra operand ‘+%s’
Try 'gdate --help' for more information.
DriversUnder25.sh: line 24: ( 1471392000 - )/60/60/24 : syntax error: operand expected (error token is ")/60/60/24 ")
这是我的代码:
#!/bin/bash
# define directory to search and current date
DIRECTORY="/*.xml"
CURRENT_DATE=$(date '+%Y%m%d')
# loop over files in a directory
for FILE in $DIRECTORY;
do
# grab user's birth date from XML file
BIRTH_DATE=$(sed -n '/Birthdate/{s/.*<Birthdate>//;s/<\/Birthdate.*//;p;}' $FILE)
# calculate the difference between the current date
# and the user's birth date (seconds)
DIFFERENCE=$(( ( $(gdate -ud $CURRENT_DATE +'%s') - $(gdate -ud $BIRTH_DATE +'%s') )/60/60/24 ))
# calculate the number of years between
# the current date and the user's birth date
YEARS=$(($DIFFERENCE / 365))
# if the user is under 25
if [ "$YEARS" -le 25 ]; then
# save file name only
FILENAME=`basename $FILE`
# output filename to text file
echo $FILENAME >> DriversUnder25.txt
fi
done
我不确定为什么它正确输出前 10 个文件名然后停止。为什么会发生这种情况的任何想法?
您需要引用 $BIRTH_DATE
的扩展,以防止值中的空格出现分词。 (最好引用 所有 你的参数扩展,除非你有充分的理由不这样做,因为这个原因。)
DIFFERENCE=$(( ( $(gdate -ud "$CURRENT_DATE" +'%s') - $(gdate -ud "$BIRTH_DATE" +'%s') )/60/60/24 ))
(根据您的评论,这可能至少会让 gdate
给您更好的错误消息。)
最佳实践实施如下所示:
directory=/ # patch as appropriate
current_date_unix=$(date +%s)
for file in "$directory"/*.xml; do
while IFS= read -r birth_date; do
birth_date_unix=$(gdate -ud "$birth_date" +'%s')
difference=$(( ( current_date_unix - birth_date_unix ) / 60 / 60 / 24 ))
years=$(( difference / 365 ))
if (( years < 25 )); then
echo "${file%.*}"
fi
done < <(xmlstarlet sel -t -m '//Birthdate' -v . -n <"$file")
done >DriversUnder25.txt
如果没有安装 xmlstarlet
的朋友们需要使用此脚本,您可以生成一个 XSLT 模板,然后使用 xsltproc
(现成可用)现代操作系统上的盒子)。
也就是说,如果您 运行 这一次,并将其输出与您的脚本捆绑在一起:
xmlstarlet sel -C -t -m '//Birthdate' -v . -n >get-birthdays.xslt
...然后可以修改脚本以将 xmlstarlet
替换为:
xsltproc get-birthdays.xslt - <"$file"
备注:
- 正在使用 an actual XML parser 读取 XML 个输入文件。
- 当扩展
for file in "$directory"/*.xml
时,扩展被引用但 glob 不是(因此允许脚本对名称中包含空格、glob 字符等的目录进行操作)。
- 输出文件被打开一次,用于循环,而不是每行输出一次(减少不必要的打开和关闭文件的开销)。
- 使用小写变量名以符合 POSIX conventions(指定对操作系统有意义的变量和 shell 具有全大写名称,并且具有至少一个小写字符的名称保留供应用程序使用;而所讨论的文档是关于环境变量的,shell 变量共享一个命名空间,使约定相关)。
问题是某些文件中有多个驱动程序,因此将多个出生日期导入到同一个字符串中。我的解决方案如下:
#!/bin/bash
# define directory to search and current date
DIRECTORY="/*.xml"
CURRENT_DATE=$(date '+%Y%m%d')
# loop over files in a directory
for FILE in $DIRECTORY;
do
# set flag for output to false initially
FLAG=false
# grab user's birth date from XML file
BIRTH_DATE=$(sed -n '/Birthdate/{s/.*<Birthdate>//;s/<\/Birthdate.*//;p;}' $FILE)
# loop through birth dates in file (there can be multiple drivers)
for BIRTHDAY in $BIRTH_DATE;
do
# calculate the difference between the current date
# and the user's birth date (seconds)
DIFFERENCE=$(( ( $(gdate -ud $CURRENT_DATE +'%s') - $(gdate -ud $BIRTHDAY +'%s') )/60/60/24))
# calculate the number of years between
# the current date and the user's birth date
YEARS=$(($DIFFERENCE / 365))
# if the user is under 25
if [ "$YEARS" -le 25 ]; then
# save file name only
FILENAME=`basename $FILE`
# set flag to true (driver is under 25 years of age)
FLAG=true
fi
done
# if there is a driver under 25 in the file
if $FLAG == true; then
# output filename to text file
echo $FILENAME >> DriversUnder25.txt
fi
done
我是 bash 脚本编写新手,我的一个脚本有问题。在从充满 XML 文件的文件夹中读取他们的生日并计算他们的年龄后,我试图编写一份 25 岁以下司机的列表。一旦我确定他们未满 25 岁,driver 的数据的文件名就会保存到一个文本文件中。该脚本一直运行到某个点,然后停止。我得到的错误是:
gdate: extra operand ‘+%s’
Try 'gdate --help' for more information.
DriversUnder25.sh: line 24: ( 1471392000 - )/60/60/24 : syntax error: operand expected (error token is ")/60/60/24 ")
这是我的代码:
#!/bin/bash
# define directory to search and current date
DIRECTORY="/*.xml"
CURRENT_DATE=$(date '+%Y%m%d')
# loop over files in a directory
for FILE in $DIRECTORY;
do
# grab user's birth date from XML file
BIRTH_DATE=$(sed -n '/Birthdate/{s/.*<Birthdate>//;s/<\/Birthdate.*//;p;}' $FILE)
# calculate the difference between the current date
# and the user's birth date (seconds)
DIFFERENCE=$(( ( $(gdate -ud $CURRENT_DATE +'%s') - $(gdate -ud $BIRTH_DATE +'%s') )/60/60/24 ))
# calculate the number of years between
# the current date and the user's birth date
YEARS=$(($DIFFERENCE / 365))
# if the user is under 25
if [ "$YEARS" -le 25 ]; then
# save file name only
FILENAME=`basename $FILE`
# output filename to text file
echo $FILENAME >> DriversUnder25.txt
fi
done
我不确定为什么它正确输出前 10 个文件名然后停止。为什么会发生这种情况的任何想法?
您需要引用 $BIRTH_DATE
的扩展,以防止值中的空格出现分词。 (最好引用 所有 你的参数扩展,除非你有充分的理由不这样做,因为这个原因。)
DIFFERENCE=$(( ( $(gdate -ud "$CURRENT_DATE" +'%s') - $(gdate -ud "$BIRTH_DATE" +'%s') )/60/60/24 ))
(根据您的评论,这可能至少会让 gdate
给您更好的错误消息。)
最佳实践实施如下所示:
directory=/ # patch as appropriate
current_date_unix=$(date +%s)
for file in "$directory"/*.xml; do
while IFS= read -r birth_date; do
birth_date_unix=$(gdate -ud "$birth_date" +'%s')
difference=$(( ( current_date_unix - birth_date_unix ) / 60 / 60 / 24 ))
years=$(( difference / 365 ))
if (( years < 25 )); then
echo "${file%.*}"
fi
done < <(xmlstarlet sel -t -m '//Birthdate' -v . -n <"$file")
done >DriversUnder25.txt
如果没有安装 xmlstarlet
的朋友们需要使用此脚本,您可以生成一个 XSLT 模板,然后使用 xsltproc
(现成可用)现代操作系统上的盒子)。
也就是说,如果您 运行 这一次,并将其输出与您的脚本捆绑在一起:
xmlstarlet sel -C -t -m '//Birthdate' -v . -n >get-birthdays.xslt
...然后可以修改脚本以将 xmlstarlet
替换为:
xsltproc get-birthdays.xslt - <"$file"
备注:
- 正在使用 an actual XML parser 读取 XML 个输入文件。
- 当扩展
for file in "$directory"/*.xml
时,扩展被引用但 glob 不是(因此允许脚本对名称中包含空格、glob 字符等的目录进行操作)。 - 输出文件被打开一次,用于循环,而不是每行输出一次(减少不必要的打开和关闭文件的开销)。
- 使用小写变量名以符合 POSIX conventions(指定对操作系统有意义的变量和 shell 具有全大写名称,并且具有至少一个小写字符的名称保留供应用程序使用;而所讨论的文档是关于环境变量的,shell 变量共享一个命名空间,使约定相关)。
问题是某些文件中有多个驱动程序,因此将多个出生日期导入到同一个字符串中。我的解决方案如下:
#!/bin/bash
# define directory to search and current date
DIRECTORY="/*.xml"
CURRENT_DATE=$(date '+%Y%m%d')
# loop over files in a directory
for FILE in $DIRECTORY;
do
# set flag for output to false initially
FLAG=false
# grab user's birth date from XML file
BIRTH_DATE=$(sed -n '/Birthdate/{s/.*<Birthdate>//;s/<\/Birthdate.*//;p;}' $FILE)
# loop through birth dates in file (there can be multiple drivers)
for BIRTHDAY in $BIRTH_DATE;
do
# calculate the difference between the current date
# and the user's birth date (seconds)
DIFFERENCE=$(( ( $(gdate -ud $CURRENT_DATE +'%s') - $(gdate -ud $BIRTHDAY +'%s') )/60/60/24))
# calculate the number of years between
# the current date and the user's birth date
YEARS=$(($DIFFERENCE / 365))
# if the user is under 25
if [ "$YEARS" -le 25 ]; then
# save file name only
FILENAME=`basename $FILE`
# set flag to true (driver is under 25 years of age)
FLAG=true
fi
done
# if there is a driver under 25 in the file
if $FLAG == true; then
# output filename to text file
echo $FILENAME >> DriversUnder25.txt
fi
done