【问题标题】:Bash script expecting then, when else is neededBash 脚本期待然后,当需要时
【发布时间】:2017-02-27 10:14:46
【问题描述】:

我正在尝试在 Ubuntu 12.04 中运行一个名为 graphhopper.sh 的 shell 脚本,该脚本由网站提供。当我运行它时,终端会产生

: not found.sh: 2: graphhopper.sh: 
graphhopper.sh: 39: graphhopper.sh: Syntax error: "else" unexpected (expecting "then")

shell文件中从37开始的行是,

   if [ ${OSM_FILE: -4} == ".pbf" ]; then
       wget -O $OSM_FILE $LINK
    else    
       # make sure aborting download does not result in loading corrupt osm file
       TMP_OSM=temp.osm
       wget -O - $LINK | bzip2 -d > $TMP_OSM
       mv $TMP_OSM $OSM_FILE
    fi

    if [ ! -f "$OSM_FILE" ]; then
      echo "ERROR couldn't download or extract OSM file $OSM_FILE ... exiting"
      exit
    fi
  else
    echo "## using existing osm file $OSM_FILE"
  fi

这是整个 shell 脚本。

#!/bin/bash

GH_HOME=$(dirname $0)
JAVA=$JAVA_HOME/bin/java
if [ "x$JAVA_HOME" = "x" ]; then
 JAVA=java
fi

vers=`$JAVA -version 2>&1 | grep "java version" | awk '{print $3}' | tr -d \"`
bit64=`$JAVA -version 2>&1 | grep "64-Bit"`
if [ "x$bit64" != "x" ]; then
  vers="$vers (64bit)"
fi
echo "## using java $vers from $JAVA_HOME"

CONFIG=config.properties
if [ ! -f "config.properties" ]; then
  cp config-example.properties $CONFIG
fi

ACTION=$1
FILE=$2

USAGE="./graphhopper.sh import|ui|test <your-osm-file>"
if [ "x$ACTION" = "x" ]; then
 echo -e "## action $ACTION not found. try \n$USAGE"
fi

function ensureOsmXml { 
  if [ ! -s "$OSM_FILE" ]; then
    echo "File not found '$OSM_FILE'. Press ENTER to get it from: $LINK"
    echo "Press CTRL+C if you do not have enough disc space or you don't want to download several MB."
    read -e

    echo "## now downloading OSM file from $LINK and extracting to $OSM_FILE"

    if [ ${OSM_FILE: -4} == ".pbf" ]; then
       wget -O $OSM_FILE $LINK
    else    
       # make sure aborting download does not result in loading corrupt osm file
       TMP_OSM=temp.osm
       wget -O - $LINK | bzip2 -d > $TMP_OSM
       mv $TMP_OSM $OSM_FILE
    fi

    if [ ! -f "$OSM_FILE" ]; then
      echo "ERROR couldn't download or extract OSM file $OSM_FILE ... exiting"
      exit
#    fi
  else
    echo "## using existing osm file $OSM_FILE"
  fi
}

function ensureMaven {
  # maven home existent?
  if [ "x$MAVEN_HOME" = "x" ]; then
    # not existent but probably is maven in the path?
    MAVEN_HOME=`mvn -v | grep "Maven home" | cut -d' ' -f3`
    if [ "x$MAVEN_HOME" = "x" ]; then
      # try to detect previous downloaded version
      MAVEN_HOME="$GH_HOME/maven"
      if [ ! -f "$MAVEN_HOME/bin/mvn" ]; then
        echo "No Maven found in the PATH. Now downloading+installing it to $MAVEN_HOME"
        cd "$GH_HOME"
        MVN_PACKAGE=apache-maven-3.0.5
        wget -O maven.zip http://www.eu.apache.org/dist/maven/maven-3/3.0.5/binaries/$MVN_PACKAGE-bin.zip
        unzip maven.zip
        mv $MVN_PACKAGE maven
        rm maven.zip
      fi
    fi
  fi
}

function packageCoreJar {
  if [ ! -f "$JAR" ]; then
    echo "## now building graphhopper jar: $JAR"
    echo "## using maven at $MAVEN_HOME"
    #mvn clean
    "$MAVEN_HOME/bin/mvn" -f "$GH_HOME/core/pom.xml" -DskipTests=true install assembly:single > /tmp/graphhopper-compile.log
    returncode=$?
    if [[ $returncode != 0 ]] ; then
        echo "## compilation failed"
        cat /tmp/graphhopper-compile.log
        exit $returncode
    fi      
  else
    echo "## existing jar found $JAR"
  fi
}

function prepareEclipse {
 ensureMaven   
 packageCoreJar
 cp core/target/graphhopper-*-android.jar android/libs/   
}


## now handle actions which do not take an OSM file
if [ "x$ACTION" = "xclean" ]; then
 rm -rf */target
 exit

elif [ "x$ACTION" = "xeclipse" ]; then
 prepareEclipse
 exit

elif [ "x$ACTION" = "xandroid" ]; then
 prepareEclipse
 "$MAVEN_HOME/bin/mvn" -f "$GH_HOME/android/pom.xml" install android:deploy android:run
 exit
fi

if [ "x$FILE" = "x" ]; then
  echo -e "no file specified? try \n$USAGE"
  exit
fi

# NAME = file without extension if any
NAME="${FILE%.*}"

if [ ${FILE: -4} == ".osm" ]; then
   OSM_FILE=$FILE
elif [ ${FILE: -4} == ".pbf" ]; then
   OSM_FILE=$FILE
elif [ ${FILE: -7} == ".osm.gz" ]; then
   OSM_FILE=$FILE
else
   # no end default to osm
   OSM_FILE=$NAME.osm
fi

GRAPH=$NAME-gh
VERSION=`grep  "<name>" -A 1 pom.xml | grep version | cut -d'>' -f2 | cut -d'<' -f1`
JAR=core/target/graphhopper-$VERSION-jar-with-dependencies.jar

# file without path (.osm.gz or osm.bz2 is also possible)
TMP=$(basename "$FILE")
TMP="${TMP%.*}"
TMP="${TMP%.*}"


if [ "x$TMP" = "xunterfranken" ]; then
 LINK="http://download.geofabrik.de/openstreetmap/europe/germany/bayern/unterfranken.osm.bz2"
 JAVA_OPTS="-XX:PermSize=60m -XX:MaxPermSize=60m -Xmx200m -Xms200m" 
elif [ "x$TMP" = "xgermany" ]; then
 LINK=http://download.geofabrik.de/openstreetmap/europe/germany.osm.bz2

 # Info: for import we need a more memory than for just loading it
 JAVA_OPTS="-XX:PermSize=60m -XX:MaxPermSize=60m -Xmx1600m -Xms1600m" 
else 
 LINK=`echo $NAME | tr '_' '/'`
 if [ ${FILE: -4} == ".osm" ]; then 
   LINK="http://download.geofabrik.de/$LINK-latest.osm.bz2"
 else
   LINK="http://download.geofabrik.de/$LINK-latest.osm.pbf"
 fi
 if [ "x$JAVA_OPTS" = "x" ]; then
  JAVA_OPTS="-XX:PermSize=60m -XX:MaxPermSize=60m -Xmx1000m -Xms1000m" 
 fi
fi



ensureOsmXml
ensureMaven
packageCoreJar

echo "## now $ACTION. JAVA_OPTS=$JAVA_OPTS"

if [ "x$ACTION" = "xui" ] || [ "x$ACTION" = "xweb" ]; then
 export MAVEN_OPTS="$MAVEN_OPTS $JAVA_OPTS"
 "$MAVEN_HOME/bin/mvn" -f "$GH_HOME/web/pom.xml" -Dgraphhopper.config=$CONFIG \
      -Dgraphhopper.osmreader.osm=$OSM_FILE -Djetty.reload=manual jetty:run


elif [ "x$ACTION" = "ximport" ]; then
 "$JAVA" $JAVA_OPTS -cp "$JAR" com.graphhopper.GraphHopper printVersion=true config=$CONFIG \
      graph.location="$GRAPH" \
      osmreader.osm="$OSM_FILE"


elif [ "x$ACTION" = "xtest" ]; then
 "$JAVA" $JAVA_OPTS -cp "$JAR" com.graphhopper.GraphHopper printVersion=true config=$CONFIG \
       graph.location="$GRAPH" osmreader.osm="$OSM_FILE" prepare.chShortcuts=false \
       graph.testIT=true


elif [ "x$ACTION" = "xmeasurement" ]; then
 ARGS="graph.location=$GRAPH osmreader.osm=$OSM_FILE prepare.chShortcuts=fastest osmreader.acceptWay=CAR"
 echo -e "\ncreate graph via $ARGS, $JAR"
 START=$(date +%s)
 "$JAVA" $JAVA_OPTS -cp "$JAR" com.graphhopper.GraphHopper $ARGS prepare.doPrepare=false
 END=$(date +%s)
 IMPORT_TIME=$(($END - $START))000

 function startMeasurement {
    COUNT=5000
    ARGS="$ARGS prepare.doPrepare=true measurement.count=$COUNT measurement.location=$M_FILE_NAME graph.importTime=$IMPORT_TIME"
    echo -e "\nperform measurement via $ARGS, $JAR"
    "$JAVA" $JAVA_OPTS -cp "$JAR" com.graphhopper.util.Measurement $ARGS
 }

 # use all <last_commits> versions starting from HEAD
 last_commits=$3

 if [ "x$last_commits" = "x" ]; then
   # use current version
   "$MAVEN_HOME/bin/mvn" -f "$GH_HOME/core/pom.xml" -DskipTests clean install assembly:single
   startMeasurement
   exit
 fi

 commits=$(git rev-list HEAD -n $last_commits)
 for commit in $commits; do
   git checkout $commit -q
   M_FILE_NAME=`git log -n 1 --pretty=oneline | grep -o "\ .*" |  tr " ,;" "_"`
   M_FILE_NAME="measurement$M_FILE_NAME.properties"
   echo -e "\nusing commit $commit and $M_FILE_NAME"

   "$MAVEN_HOME/bin/mvn" -f "$GH_HOME/core/pom.xml" -DskipTests clean install assembly:single
   startMeasurement
 done

fi

【问题讨论】:

  • 第一条错误消息看起来像是 DOS 风格的行尾(即回车后跟换行,而不仅仅是换行)。尝试使用cat -v graphhopper.sh 打印脚本并在行尾查找“^M”。
  • 是的,有很多^Ms。我现在能做什么?

标签: bash shell syntax-error ubuntu-12.04 graphhopper


【解决方案1】:

[从我的评论扩展...] 脚本文件显然具有 DOS 样式的行尾(即回车后跟换行,而不仅仅是换行)。这极大地混淆了 shell,因为它将回车视为命令的一部分。赠品是第一条错误消息:

: not found.sh: 2: graphhopper.sh: 

实际发生的是它打印了错误消息“graphhopper.sh: 2: graphhopper.sh: ^M: not found”(^M 实际上是回车);当终端看到 ^M 时,它会回到行首,并在开头的顶部打印错误消息的结尾。

它的其他影响之一是 shell 无法识别行尾的关键字。当它看到这样的一行时:

if [ ${OSM_FILE: -4} == ".pbf" ]; then^M

...它认为then^M 是常规命令,而不是if 命令的条件部分的结尾,因此它一直在寻找then。但是else这个命令最后好像有一些空格:

else    ^M

...这意味着 shell确实 识别了 else 关键字,并且对它在 if 的条件部分中间所做的事情感到非常困惑。

那么你能做些什么呢?几乎可以肯定它有一个命令。我习惯了dos2unix,但显然ubuntu 没有,而是“tofrodos”包包含命令fromdos(参见here)。或者,您可以使用 perl 来完成:

perl -pi -e 's/\r//g' graphhopper.sh

您的文本编辑器也可以保存为 unix(而不是 DOS)格式。说到这一点,您应该将您的文本编辑器切换到 unix 模式,或者找到一个不同的文本编辑器来编写脚本。

【讨论】:

  • 哇,非常感谢。这就是问题所在。使用 fromdos 命令轻松纠正。
【解决方案2】:

去掉多余的fi:

    if [ ! -f "$OSM_FILE" ]; then
      echo "ERROR couldn't download or extract OSM file $OSM_FILE ... exiting"
      exit
  #   fi
    else
      echo "## using existing osm file $OSM_FILE"
    fi

【讨论】:

  • 您的删节示例并不能说明问题。请包含整个脚本。
  • 我修改了我的原始帖子以包含整个脚本@Brian。请看一下。
【解决方案3】:

变量 OSM_FILE 未设置为任何值。这会导致它扩展为一个空字符串,从而导致 shell 认为 if 条件中有语法错误。

使用前打印出OSM_FILE的值,如果为空则向后调试。

【讨论】:

  • 是的。 OSM_FILE 值在运行时设置。当我将 shell 脚本作为 './graphhopper import new-York.osm' 运行时,我必须传递一个值
  • 对。但是你确认了吗。通过在您遇到问题的区域周围的脚本中插入一个 echo 语句。此外,您需要重新输入有人要求您发表评论的“fi”。
  • 我对 shell 脚本了解不多。请准确告诉我应该在哪里设置 echo 语句并进行检查?
  • 问题是文件中存在 DOS 行结尾,正如 OP 所确认的那样。
猜你喜欢
  • 2018-07-05
  • 2020-08-31
  • 2018-11-12
  • 1970-01-01
  • 2015-06-22
  • 1970-01-01
  • 2011-04-27
  • 2016-11-17
  • 1970-01-01
相关资源
最近更新 更多