根据 getopts 标志更改函数中的变量 bash
Changing variable in function dependant on getopts flag bash
我有一个 bash 脚本可以找到连接的设备并将串口输出记录到一个文件中。
我正在使用 getopts 来选择记录的方法。
除了一行之外,其中两个功能相同。
我想将它更改为一个函数,其中一个变量用于不同的单行(我的尝试在下面)但没有成功。我怎样才能用 getopts 做到这一点?
非常感谢。
#!/bin/bash
#script to capture camera serial port logs via usb or UART.
file_name='DashcamLog'
#Date e.g: 20210204T120159 (ISO 8601)
current_date=$(date +%Y%m%dT%H%M%S)
BAUDRATE='115200'
#change to reflect udev rules e.g /dev/h1*
BOARDS=(/dev/ttyUSB* /dev/ttyACM*)
screen="$(screen -Sdm $port_name -L -Logfile $new_file_name $i $BAUDRATE)"
minicom="$(screen -Sdm ${port_name} minicom -b ${BAUDRATE} -D ${i} -C ${new_file_name})"
usage() {
echo "Usage:"
echo "Use [=11=] -a to use GNU screen to automatically capture logs on USB plug in"
echo "Use [=11=] -s to use GNU screen to capture logs WITHOUT automatic capture on USB plug in."
echo "Use [=11=] -m to use minicom to capture logs WITHOUT automatic capture on USB plug in."
}
#detects current + new devices + automatically starts logging
autoStartLog() {
while true;do
current_date=$(date +%Y%m%dT%H%M%S)
for i in $BOARDS; do
port_name=${i#/dev/}
if ! screen -ls | grep -o $port_name > /dev/null;then
(
serial_no="$(udevadm info --attribute-walk $i | grep -m 1 ATTRS{serial})"
#file name e.g = DashcamLog_20210208T094013_peri_h1p1.log
new_file_name="${file_name}_${current_date}_${HOSTNAME}_${port_name}.log"
$screen
echo $port_name 'serial_no: ' $serial_no $new_file_name
)
fi
done
done
}
#detects current devices + starts logging using screen(-s)/minicom(-m)
startLog() {
for i in $BOARDS; do
(
port_name=${i#/dev/}
serial_no="$(udevadm info --attribute-walk $i | grep -m 1 ATTRS{serial})"
new_file_name="${file_name}_${current_date}_${HOSTNAME}_${port_name}.log"
echo $port_name 'serial_no: ' $serial_no $new_file_name
)
done
}
while getopts ":hmsa" opt; do
case ${opt} in
h)
usage
;;
a)
autoStartLog
;;
s)
startLog $screen
;;
m)
startLog $minicom
;;
\? )
echo "Invalid Option: -$OPTARG" 1>&2
usage
exit 1
;;
esac
done
shift $((OPTIND -1))
我更改了一些内容,因为我意识到在评论中解释所有小细节会太长。
代码如下:
#!/bin/bash
#script to capture camera serial port logs via usb or UART.
file_name='DashcamLog'
#Date e.g: 20210204T120159 (ISO 8601)
current_date=$(date +%Y%m%dT%H%M%S)
BAUDRATE='115200'
#change to reflect udev rules e.g /dev/h1*
BOARDS=(/dev/ttyUSB* /dev/ttyACM*)
usage()
{
echo "Usage:"
echo "Use [=10=] -a to use GNU screen to automatically capture logs on USB plug in"
echo "Use [=10=] -s to use GNU screen to capture logs WITHOUT automatic capture on USB plug in."
echo "Use [=10=] -m to use minicom to capture logs WITHOUT automatic capture on USB plug in."
exit 1
}
#detects current devices + starts logging using screen(-s)/minicom(-m)
startLog()
{
for i in "${BOARDS[@]}"
do
port_name="${i#/dev/}"
serial_no=$(udevadm info --attribute-walk "$i" | grep -m 1 "ATTRS{serial}")
new_file_name="${file_name}_${current_date}_${HOSTNAME}_${port_name}.log"
case "" in
"screen")
echo "PUT THE SCREEN COMMAND HERE"
;;
"minicom")
echo "PUT THE MINICOM COMMAND HERE"
;;
\?)
echo "Invalid Option: -$OPTARG" 1>&2
usage
;;
esac
echo "$port_name serial_no: $serial_no $new_file_name"
done
}
while getopts ":hms" opt
do
case "$opt" in
h)
usage
;;
s)
startLog screen
;;
m)
startLog minicom
;;
\?)
echo "Invalid Option: -$OPTARG" 1>&2
usage
;;
esac
done
shift $((OPTIND -1))
详情:
- 当您定义变量 screen 和 minicom 时,您有
"$( ... )"
。 $()
中的命令会立即执行,而不是在稍后放置 </code> 时才执行。这就是为什么我删除了那部分并将命令直接放在函数中的原因。</li>
<li>在startLog()中,我重用了一个<code>case
。也可以使用 if
。
BOARDS
是一个数组。所以当你做 $BOARDS
时,没有指定索引,你只会得到第一项。您必须 ${BOARDS[@]}
才能处理所有项目。
- 如果您不知道,
BOARDS=(/dev/ttyUSB* /dev/ttyACM*)
将扩展 *
,因此 BOARDS 将被定义为所有文件 /dev/ttyUSB*
和所有文件 /dev/ttyACM*
。它不会“留在” *
.
- 当您从另一个命令 (
var=$(command)
) 定义一个变量时,您不需要在它周围放置 " "
。这也令人困惑,因为您应该在 $()
中使用双引号变量,这样您就会在其他双引号中使用双引号。
我也把它放在我喜欢的代码风格中,但那是灵活的,取决于个人喜好。
您可以将代码放入 https://www.shellcheck.net/ 以验证语法。
我有一个 bash 脚本可以找到连接的设备并将串口输出记录到一个文件中。 我正在使用 getopts 来选择记录的方法。 除了一行之外,其中两个功能相同。 我想将它更改为一个函数,其中一个变量用于不同的单行(我的尝试在下面)但没有成功。我怎样才能用 getopts 做到这一点? 非常感谢。
#!/bin/bash
#script to capture camera serial port logs via usb or UART.
file_name='DashcamLog'
#Date e.g: 20210204T120159 (ISO 8601)
current_date=$(date +%Y%m%dT%H%M%S)
BAUDRATE='115200'
#change to reflect udev rules e.g /dev/h1*
BOARDS=(/dev/ttyUSB* /dev/ttyACM*)
screen="$(screen -Sdm $port_name -L -Logfile $new_file_name $i $BAUDRATE)"
minicom="$(screen -Sdm ${port_name} minicom -b ${BAUDRATE} -D ${i} -C ${new_file_name})"
usage() {
echo "Usage:"
echo "Use [=11=] -a to use GNU screen to automatically capture logs on USB plug in"
echo "Use [=11=] -s to use GNU screen to capture logs WITHOUT automatic capture on USB plug in."
echo "Use [=11=] -m to use minicom to capture logs WITHOUT automatic capture on USB plug in."
}
#detects current + new devices + automatically starts logging
autoStartLog() {
while true;do
current_date=$(date +%Y%m%dT%H%M%S)
for i in $BOARDS; do
port_name=${i#/dev/}
if ! screen -ls | grep -o $port_name > /dev/null;then
(
serial_no="$(udevadm info --attribute-walk $i | grep -m 1 ATTRS{serial})"
#file name e.g = DashcamLog_20210208T094013_peri_h1p1.log
new_file_name="${file_name}_${current_date}_${HOSTNAME}_${port_name}.log"
$screen
echo $port_name 'serial_no: ' $serial_no $new_file_name
)
fi
done
done
}
#detects current devices + starts logging using screen(-s)/minicom(-m)
startLog() {
for i in $BOARDS; do
(
port_name=${i#/dev/}
serial_no="$(udevadm info --attribute-walk $i | grep -m 1 ATTRS{serial})"
new_file_name="${file_name}_${current_date}_${HOSTNAME}_${port_name}.log"
echo $port_name 'serial_no: ' $serial_no $new_file_name
)
done
}
while getopts ":hmsa" opt; do
case ${opt} in
h)
usage
;;
a)
autoStartLog
;;
s)
startLog $screen
;;
m)
startLog $minicom
;;
\? )
echo "Invalid Option: -$OPTARG" 1>&2
usage
exit 1
;;
esac
done
shift $((OPTIND -1))
我更改了一些内容,因为我意识到在评论中解释所有小细节会太长。
代码如下:
#!/bin/bash
#script to capture camera serial port logs via usb or UART.
file_name='DashcamLog'
#Date e.g: 20210204T120159 (ISO 8601)
current_date=$(date +%Y%m%dT%H%M%S)
BAUDRATE='115200'
#change to reflect udev rules e.g /dev/h1*
BOARDS=(/dev/ttyUSB* /dev/ttyACM*)
usage()
{
echo "Usage:"
echo "Use [=10=] -a to use GNU screen to automatically capture logs on USB plug in"
echo "Use [=10=] -s to use GNU screen to capture logs WITHOUT automatic capture on USB plug in."
echo "Use [=10=] -m to use minicom to capture logs WITHOUT automatic capture on USB plug in."
exit 1
}
#detects current devices + starts logging using screen(-s)/minicom(-m)
startLog()
{
for i in "${BOARDS[@]}"
do
port_name="${i#/dev/}"
serial_no=$(udevadm info --attribute-walk "$i" | grep -m 1 "ATTRS{serial}")
new_file_name="${file_name}_${current_date}_${HOSTNAME}_${port_name}.log"
case "" in
"screen")
echo "PUT THE SCREEN COMMAND HERE"
;;
"minicom")
echo "PUT THE MINICOM COMMAND HERE"
;;
\?)
echo "Invalid Option: -$OPTARG" 1>&2
usage
;;
esac
echo "$port_name serial_no: $serial_no $new_file_name"
done
}
while getopts ":hms" opt
do
case "$opt" in
h)
usage
;;
s)
startLog screen
;;
m)
startLog minicom
;;
\?)
echo "Invalid Option: -$OPTARG" 1>&2
usage
;;
esac
done
shift $((OPTIND -1))
详情:
- 当您定义变量 screen 和 minicom 时,您有
"$( ... )"
。$()
中的命令会立即执行,而不是在稍后放置</code> 时才执行。这就是为什么我删除了那部分并将命令直接放在函数中的原因。</li> <li>在startLog()中,我重用了一个<code>case
。也可以使用if
。 BOARDS
是一个数组。所以当你做$BOARDS
时,没有指定索引,你只会得到第一项。您必须${BOARDS[@]}
才能处理所有项目。- 如果您不知道,
BOARDS=(/dev/ttyUSB* /dev/ttyACM*)
将扩展*
,因此 BOARDS 将被定义为所有文件/dev/ttyUSB*
和所有文件/dev/ttyACM*
。它不会“留在”*
. - 当您从另一个命令 (
var=$(command)
) 定义一个变量时,您不需要在它周围放置" "
。这也令人困惑,因为您应该在$()
中使用双引号变量,这样您就会在其他双引号中使用双引号。
我也把它放在我喜欢的代码风格中,但那是灵活的,取决于个人喜好。
您可以将代码放入 https://www.shellcheck.net/ 以验证语法。