bash 中的 ANSI C 引号被添加到我的代码中

ANSI C quotes getting added to my code in bash

我正在编写一个脚本来构建一个 CSV 文件以导入到我们的 LMS。脚本的功能之一对用户的 guid 执行 ldapsearch。该命令如下所示:

ldapsearch -x -h ldap.example.com -b ou=person,dc=example,dc=com user=username

命令本身运行良好。但是,在作为 while 循环一部分的函数中,它失败了。当我在 bash 中设置 xtrace 时,我看到命令输出如下:

ldapsearch -x -h ldap.example.com -b ou=person,dc=example,dc=com $'user=username\r'

经过几个小时的搜索,$' \r' 似乎被称为 ANSI C 引号,我对它没有太多经验。问题是,为什么这个论点一开始就被这些引号包围了?其次,我该如何逃脱?

现在,更重要的是,这个脚本有 3 个函数,它们是 运行,具体取决于脚本的参数。 User functionEnrollment functionCourse function(尚未完成)。该问题仅发生在 Enrollment function 中,但是在 User function 中,相同的循环工作 100% 没有问题,并且代码一行一行地相同,所以给出了什么?

如果能在这方面提供任何帮助,我将不胜感激,如果是在我拔掉剩下的头发之前,我们将不胜感激。

下面是变量和受影响的函数代码:

受影响的行是:

found=$(${ldap_cmd}=${course_instructor} | grep numEntries: | awk -F: '{print $NF}' | sed -e 's/^[ \t]*//')

此行测试用户是否存在于 LDAP 中。

#!/bin/bash

# Set Global variables here
export PATH=/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
export ldap_host="ldap.example.com"
export ldap_base="ou=person,dc=example,dc=com"
export ldap_cmd="ldapsearch -x -h ${ldap_host} -b ${ldap_base} user"
export script_name=$(basename "[=14=]"| cut -d. -f1)
export script_pid=$(pgrep "${script_name}")
export admin_id=$(whoami)
export admin_mail=$(${ldap_cmd}="${admin_id}" | grep mail: | awk -F: '{print $NF}' | tail -1 | sed -e 's/^[ \t]*//')
export admin_name=$(${ldap_cmd}="${admin_id}" | grep givenName: | awk -F: '{print $NF}' | tail -1 | sed -e 's/^[ \t]*//')
export admin_fname=$(${ldap_cmd}="${admin_id}" | grep cn: | awk -F: '{print $NF}' | tail -1 | sed -e 's/^[ \t]*//')

function enrollment_feed () {
  # Fountion specific variables
  # enrollment_feed ${input_option} ${term_option} ${input_file}
  export input_count=$(wc -l "${input_file}" | awk '{print }')
  export enrollment_file="$(pwd)/erollments.csv"
  export error_file="$(pwd)/error.csv"

  # Create the output files enrollment and error
  echo "course_id,root_account,user_id,role,role_id,section_id,status,associated_user_id,limit_section_privileges" > "${enrollment_file}"
  echo "error" > "${error_file}"

  # main script while loop
  clear
  printf "\n========================================="
  printf "\n= Canvas SIS Import Builder Tool        ="
  printf "\n= Enrollment Feed                       ="
  printf "\n========================================="
  printf "\n${inf_msg} Preparing to run script ${orange}${script_name}${no_color}"
  sleep 0.5
  printf "\n${inf_msg} The script process ID is ${orange}${script_pid}${no_color}"
  sleep 0.5
  printf "\n${inf_msg} The script in run by: ${orange}${admin_fname}${no_color}"
  sleep 0.5
  printf "\n${inf_msg} The script will start running now"
  printf "\n========================================="
  printf "\n= Started $(date)  ="
  printf "\n========================================="
  printf "\n"
  sleep 0.5
  while IFS="," read -r course_title course_number course_section course_instructor; do
      if ! [[ "${course_number}" =~ ^[0-9]+$ ]]; then
        printf "\r${war_msg} header or blank line detected"
        tput el
        sleep 0.5
        printf "\r${war_msg} Skipping line.."
        tput el
        sleep 0.5
        printf "\r"
        tput el
        sleep 0.5
        printf "\r${bang_mark} Line Skipped.\n"
      else
        printf "\r${inf_msg} Start processing ${orange}${input_term}-${course_number}-${course_section}${no_color}..."
        tput el
        sleep 0.5
        printf "\r${inf_msg} Searching directory services for the user record matching AndrewID ${orange}${course_instructor}${no_color}"
        tput el
        sleep 0.5
        found=$(${ldap_cmd}=${course_instructor} | grep numEntries: | awk -F: '{print $NF}' | sed -e 's/^[ \t]*//')
        if [[ "${found}" = "1" ]]; then
          printf "\r${inf_msg} A user record was found in directory services matching AndrewID ${orange}${course_instructor}${no_color}"
          tput el
          sleep 0.5
          printf "\r${inf_msg} Collecting all required fields from directory services matching AndrewID ${orange}${course_instructor}${no_color}"
          tput el
          sleep 0.5
          printf "\r${inf_msg} Constructing information for ${orange}${input_term}-${course_number}-${course_section}${no_color}"
          tput el
          sleep 0.5
          course_id="${input_term}-${course_number}-${course_section}"
          root_account="canvas.cmu.edu"
          user_id=$(${ldap_cmd}="${course_instructor}" | grep guid: | awk -F: '{print $NF}' | sed -e 's/^[ \t]*//')
          role="teacher"
          role_id="4"
          section_id=""
          status="active"
          associated_user_id=""
          limit_section_privileges=""
          printf "\r${inf_msg} Exporting all required fields for course ${orange}${input_term}-${course_number}-${course_section}${no_color} to the enrollments csv file"
          tput el
          sleep 0.5
          echo ${course_id},${root_account},${user_id},${role},${role_id},${section_id},${status},${associated_user_id},${limit_section_privileges} >> "${enrollment_file}"
          printf "\r${inf_msg} All required fields for course ${orange}${input_term}-${course_number}-${course_section}${no_color} have now been exported to the enrollment csv file"
          tput el
          sleep 0.5
          printf "\r"
          tput el
          sleep 0.5
          printf "\r${check_mark} Couse/section ${orange}${input_term}-${course_number}-${course_section}${no_color} Done.\n"
        else
          printf "\r${war_msg} The was no user record matching AndrewID ${blue}${course_instructor}${no_color} in directory services"
          tput el
          sleep 0.5
          printf "\r${war_msg} Roprting this in error csv"
          tput el
          sleep 0.5
          printf "\r"
          tput el
          sleep 0.5
          printf "\r${cross_mark} Instructor for course ${red}${input_term}-${course_number}-${course_section}${no_color} not found.\n"
          echo "${input_term}-${course_number}-${course_section}" >> "${error_file}"
        fi
      fi
  done < "${input_file}"

  printf "\n========================================="
  printf "\n= Finished $(date) ="
  printf "\n========================================="
  printf "\n"
  sleep 0.5
  # send files in email to admin
  printf "\n${inf_msg} Sending email with csv files attached to ${orange}${admin_mail}${no_color}"
  sleep 0.5
  msg_body="Dear ${admin_name},\n\nPlease find attached the following two files:\n\n - enrollments.csv: (This file contains all the Instructor information needed for and enrollments SIS import in Canvas)\n - error.csv: (This file contains course id for course with no valid instrcutor id)\n\nPlease use these files responsibly and in line with CMU privcy guidelines.\n\nBest regards,\nCanvas Admin\n\n\nThe script "${script_name}" was run by ${admin_id} from ${computer_name} at $(date +"%Y-%m-%d %T%Z")"
  printf "${msg_body}" | mailx -s "Enrollments list as of $(date)" -a "${user_file}" -a "${email_file}" -a "${error_file}" "${admin_mail}"
  printf "\n${inf_msg} Email has been sent, please check your mailbox"
  sleep 0.5
  printf "\n${inf_msg} The script has now finished processing all ${input_count} records"
  sleep 0.5
  printf "\n${inf_msg} Deleting the temp csv files"
  rm -rf "${enrollment_file}"
  sleep 0.5
  rm -rf "${error_file}"
  sleep 0.5
  printf "\n${inf_msg} The script ran for ${orange}$(ps -p "${script_pid}" -o etime | tail -1 | awk '{print }')${no_color}"
  sleep 0.5
  printf "\n${inf_msg} The script is now exiting"
  sleep 0.5
  printf "\n"
  printf "\n========================================="
  printf "\n= Good Bye!                             ="
  printf "\n========================================="
  printf "\n"
  exit 0
}

您是否使用 windows 或 windows 中的文件来编写您的脚本?

\r是马车return。 Windows 使用 \r\n 开始新行。 Linux 仅使用 \n。 Bash 将 \r 解释为普通字符。

the same loop is working 100% no issues, and the code is line per line identical

您确定代码相同吗?您无法在纯文本编辑器中看到 \r\n\r 之间的区别。

尝试删除所有 \r 使用

dos2unix -n yourScriptFile yourScriptFile2

tr -d '\r' < yourScriptFile > yourScriptFile2

问题显然来自这一行

 while IFS="," read -r course_title course_number course_section course_instructor ; do

你可以看到 course_instructor 是从行尾读取的 - 当从 'wrong' 终端读取时,发送 \r 作为换行的一部分,\r 最终出现在变量中。 $'something\r' 表示法只是在 bash 命令行中包含特殊字符的一种方式。

(猜测)其他适合您的函数可能不会在立即失败的地方使用最后一个变量(包括 \r)。

快速解决方法是 a) 使用更好的终端进行数据输入,b) 通过例如 <<<"$var" tr -d '\r'.

摆脱 \r