【问题标题】:I get syntax error when i call script from c++ program从 C++ 程序调用脚本时出现语法错误
【发布时间】:2016-08-23 11:54:38
【问题描述】:

我正在尝试编写一个程序,以便更轻松地管理 Arduino 项目。所以我编写了 bash 脚本,它为我创建了所有必要的文件夹和文件,当我执行它时,我像冠军一样运行。因为我想在脚本中更改工作终端中的目录,所以我运行这样的脚本

. ./initialize.sh

这也很好用,但是因为我正在编写 C++ 程序,所以从程序中获取这个脚本让我很头疼。

所以在一个程序中我像这样运行这个脚本:

system(". /usr/lib/avrduino/script/initialize.sh");

然后当我运行程序时出现此错误:

sh:25:/usr/lib/avrduino/script/initialize.sh:语法错误:“(”意外(预期“}”)

像这样从程序运行脚本:

system("/usr/lib/avrduino/script/initialize.sh");

正常工作,但它在子shell中运行。

语法错误指向脚本中的这一行

options=("uno" "mega" "mega2560" "atmega8" "atmega168" "atmega328" "pro" "pro5v" "pro328" "pro5v328")

为什么当我在程序之外运行这个脚本时它像冠军一样工作,但是从程序运行这个脚本却有问题?

编辑: 脚本代码

   #!/bin/bash

BLACK='\033[0;30m'
RED='\033[0;31m'
GREEN='\033[0;32m'
BROWN='\033[0;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
LGRAY='\033[0;37m'
DGRAY='\033[1;30m'
LRED='\033[1;31m'
LGREEN='\033[1;32m'
YELLOW='\033[1;33m'
LBLUE='\033[1;34m'
LPURPLE='\033[1;35m'
LCYAN='\033[1;36m'
WHITE='\033[1;37m'
NC='\033[0m'

makefile()
{
  BOARD="default"
  PS3='Chose your board: '
  options=("uno" "mega" "mega2560" "atmega8" "atmega168" "atmega328" "pro" "pro5v" "pro328" "pro5v328")
  select opt in "${options[@]}"
  do case $opt in 
    "uno") BOARD="uno"
    cp -r /usr/lib/avrduino/data/boards_info/uno/board-info.h .
    MCU="atmega328P"
    F_CPU="16000000UL"
    ;;
  "mega") BOARD="mega" 
    cp -r /usr/lib/avrduino/data/boards_info/mega/board-info.h .
    F_CPU="16000000UL"
    ;;
  "mega2560") BOARD="mega2560"
    cp -r /usr/lib/avrduino/data/boards_info/mega2560/board-info.h .
    F_CPU="16000000UL"
    ;;
  "atmega8") BOARD="atmega8"
    cp -r /usr/lib/avrduino/data/boards_info/atmega8/board_-nfo.h .
    MCU="atmega8"
    F_CPU="16000000UL"
    ;;
  "atmega168") BOARD="atmega168"
    cp -r /usr/lib/avrduino/data/boards_info/atmega168/board-info.h .
    MCU="atmega168"
    F_CPU="16000000UL"
    ;;
  "atmega328") BOARD="atmega328"
    cp -r /usr/lib/avrduino/data/boards_info/atmega328/board-info.h .
    MCU="atmega328P"
    F_CPU="16000000UL"
    ;;
  "pro") BOARD="pro"
    cp -r /usr/lib/avrduino/data/boards_info/pro/board-info.h .
    MCU="unknow"
    F_CPU="16000000UL"
    ;;
  "pro5v") BOARD="pro5v"
    cp -r /usr/lib/avrduino/data/boards_info/pro5v/board-info.h .
    MCU="unknown"
    F_CPU="16000000UL"
    ;;

  "pro328") BOARD="pro328"
    cp -r /usr/lib/avrduino/data/boards_info/pro328/board-info.h .
    MCU="atmega328P"
    F_CPU="16000000UL"
    ;;
  "pro5v328") BOARD= "pro5v328"
    cp -r /usr/lib/avrduino/data/boards_info/pro5v328/board-info.h .
    MCU="atmega328P"
    F_CPU="16000000UL"
    ;;
  *)
    echo "Error : Input is not valid"
    echo "Exiting..."
    return 1 
    ;;
    esac
    break
  done
  [ -e Makefile ] && rm Makefile
  read -p "Do you want to configure your Makefile settings [Y/n]: " CONFIGURE
  if { [ "$CONFIGURE" == "Y" ] || [ "$CONFIGURE" == "y" ]; }; then
    read -p "Enter your MCU: " MCU
    read -p "Enter F_CPU: " F_CPU
  fi
  read -p "Enter ARDUINO_PORT: " ARDUINO_PORT
  echo "ARDUINO_DIR = /usr/share/arduino">>Makefile
  echo "BOARD_TAG = $BOARD">>Makefile
  echo "ARDUINO_PORT = $ARDUINO_PORT">>Makefile
  echo "NO_CORE = 1">>Makefile
  echo "AVRDUDE_ARD_PROGRAMMER = arduino">>Makefile
  echo "HEX_MAXIMUM_SIZE = 30720">>Makefile
  echo "AVRDUDE_ARD_BAUDRATE = 115200">>Makefile
  echo "#ISP_LOW_FUSE = 0xFF">>Makefile
  echo "#ISP_HIGH_FUSE = 0xDA">>Makefile
  echo "#ISP_EXT_FUSE = 0x05">>Makefile
  echo "#ISP_LOCK_FUSE_PRE = 0x3F">>Makefile
  echo "#ISP_LOCK_FUSE_POST = 0x0F">>Makefile
  echo "MCU = $MCU">>Makefile
  echo "F_CPU = $F_CPU">>Makefile
  echo "VARIANT = standard">>Makefile
  echo "ARDUINO_LIBS =">>Makefile
  echo "include /usr/share/arduino/Arduino.mk">>Makefile
  echo "$BOARD|$MCU|" >> .avrduino.txt

  clear
  echo -e "${LGREEN}Makefile settings${NC}"
  echo -e "${LBLUE}ARDUINO_DIR = ${LRED}/usr/share/arduino ${NC}"
  echo -e "${LBLUE}BOARD_TAG = ${LRED}$BOARD${NC}"
  echo -e "${LBLUE}ARDUINO_PORT = ${LRED}$ARDUINO_PORT${NC}"
  echo -e "${LBLUE}NO_CORE = ${LRED}1${NC}"
  echo -e "${LBLUE}AVRDUDE_ARD_PROGRAMMER = ${LRED}arduino${NC}"
  echo -e "${LBLUE}HEX_MAXIMUM_SIZE = ${LRED}30720${NC}"
  echo -e "${LBLUE}AVRDUDE_ARD_BAUDRATE = ${LRED}115200${NC}"
  echo -e "${DGRAY}#ISP_LOW_FUSE = ${RED}0xFF${NC}"
  echo -e "${DGRAY}#ISP_HIGH_FUSE = ${RED}0xDA${NC}"
  echo -e "${DGRAY}#ISP_EXT_FUSE = ${RED}0x05${NC}"
  echo -e "${DGRAY}#ISP_LOCK_FUSE_PRE = ${RED}0x3F${NC}"
  echo -e "${DGRAY}#ISP_LOCK_FUSE_POST = ${RED}0x0F${NC}"
  echo -e "${LBLUE}MCU = ${LRED}$MCU${NC}"
  echo -e "${LBLUE}F_CPU = ${LRED}$F_CPU${NC}"
  echo -e "${LBLUE}VARIANT = ${LRED}standard${NC}"
  echo -e "${LBLUE}ARDUINO_LIBS =${NC}"

}

initializeProject()
{
  read -p "Project name: " PROJECT_NAME
  if [ ! -e PROJECT_NAME ]; then
    mkdir $PROJECT_NAME
    cd $PROJECT_NAME
    makefile #Call function that makes makefile
    cp -r /usr/lib/avrduino/data/include/ .
    echo -e "${LGREEN}Project created successfully ${NC}"
  else 
    echo "AVRduino: Project with name [ $PROJECT_NAME ] already exists. "
    echo "AVRduino: Stop project wizard and exit."
  fi
}

clear
initializeProject

【问题讨论】:

  • 是您帖子中的拼写错误还是您的代码中实际上有. /usr
  • 脚本的第一行有#!位?
  • 。 /usr 不是错字,superuser.com/questions/176783/…
  • 这可能是 system() 实际上调用了一个不同的 shell,就像你在终端中一样。经常看到这种错误。
  • 这就是为什么我用 . /usr

标签: c++ linux bash shell


【解决方案1】:

. 不会将脚本作为进程执行,它只会将其加载到您当前的 shell 进程中。

在这种情况下,您的“shebang”行 #!/bin/bash 只是一个评论。
(您可以将#! doodle poodle noodle 放在那里,它也会运行。)

当您使用system 时,它会在/bin/sh 中执行,因此您的bash 脚本有语法错误。

执行脚本的一种方法是使其可执行:

chmod +x /usr/lib/avrduino/script/initialize.sh

然后你可以直接将它传递给system:

system("/usr/lib/avrduino/script/initialize.sh");

或者,您可以在bash 中显式执行它:

system("/bin/bash /usr/lib/avrduino/script/initialize.sh");

好的,这里有一种方法可以解决您的“更改目录”问题:

重写initialize.sh,这样它将项目名称作为参数,而不是交互地询问它(这就是普通的Unix工具的工作方式,所以坚持下去)。

然后将以下内容添加到您的.bashrc

make_project()
{
    /usr/lib/avrduino/script/initialize.sh "$1" && cd "$1"
}

然后你可以说make_project foo 并被传送到目录“foo”。

【讨论】:

  • 知道如何使用 CD 命令,以便脚本在当前终端中使用此命令时更改工作目录?
  • @ACVoltage 你不能 - 请参阅我对另一个答案的评论。您需要重新考虑您的解决方案。
【解决方案2】:

很可能是错误放置的 shebang 导致默认 shell 运行 - 确保 shebang 位于第一行的开头

#!/bin/bash
# rest of script

如果这不起作用,请将您的系统调用更改为

system("/bin/bash /usr/lib/avrduino/script/initialize.sh");

【讨论】:

  • 所以我改变了系统调用,它工作但不是我想要的方式。只是看看,也许我不明白这一点。如果我有 cd $PROJECT_NAME 是否应该更改我调用程序的终端中的工作目录。因为我的目标是。
  • 那么请接受解决方案 - 现在你有一个新问题
  • @ACVoltage system 创建一个新进程,有它自己的工作目录,你的 C++ 程序也有它自己的。更改其中任何一个都不会影响您执行程序的 shell。
猜你喜欢
  • 2014-03-28
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多