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 function
、Enrollment function
和 Course 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
我正在编写一个脚本来构建一个 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 function
、Enrollment function
和 Course 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