如何根据其他命令的输出动态构建 bash 对话框?
How to dynamically build a bash dialog from the output of an other command?
上下文
我正在尝试构建一个包含我的时间战士数据的对话框,这样我就可以直接 select 我要返回的内容而不是 timew s :ids filter_tag
,然后 time cont @12
.
因此,首先我创建了试图填充对话框选项的数据集:
timew s :ids $(date -I -d'8 days ago') - $(date -I -d'tomorrow') |
# most recent first, only the top 30 (4 additional lines are decoration)
tac | head -n 34 |
# format the whole thing as '1 "some label "' and so on
sed -ne 's:.*@::p' |
sed -e 's|\s\+[0-9]\+:.*| |g' -e's:\s\+: ":' -e's:\s*$:":' -e's:^: :'
这会生成如下所示的报告:
1 "some_info, some_info"
2 "some_info, some_info"
3 "some_info, some_info"
4 "some_info"
5 "some_info, some_info"
6 "some_info, some_info, some_info"
7 "some_info, some_info"
8 "some_info, some_info-some_info, some_info, some_info"
9 "some_info, some_info"
10 "some_info, some_info-some_info, some_info, some_info"
11 "some_info, some_info"
12 "some_info, some_info"
13 "some_info"
14 "some_info, some_info"
14 "some_info, some_info"
15 "some_info, some_info, some_info"
16 "some_info, some_info, some_info, some_info, some_info, some_info"
17 "some_info, some_info, some_info"
18 "some_info"
19 "some_info, some_info"
20 "some_info"
21 "some_info, some_info, some_info, some_info, some_info, some_info"
22 "some_info, some_info"
23 "some_info, some_info, some_info, some_info, some_info, some_info"
24 "some_info, some_info45, some_info some_info some_info, some_info"
25 "some_info"
26 "some_info"
27 "some_info, some_info, some_info"
28 "some_info, some_info, some_info, some_info"
29 "some_info, some_info, some_info"
30 "some_info"
对话框脚手架
所以我找到了这个脚手架
#!/bin/bash
HEIGHT=15
WIDTH=40
CHOICE_HEIGHT=4
BACKTITLE="Backtitle here"
TITLE="Title here"
MENU="Choose one of the following options:"
OPTIONS=(1 "Option 1"
2 "Option 2"
3 "Option 3")
CHOICE=$(dialog --clear \
--backtitle "$BACKTITLE" \
--title "$TITLE" \
--menu "$MENU" \
$HEIGHT $WIDTH $CHOICE_HEIGHT \
"${OPTIONS[@]}" \
2>&1 >/dev/tty)
clear
case $CHOICE in
1)
echo "You chose Option 1"
;;
2)
echo "You chose Option 2"
;;
3)
echo "You chose Option 3"
;;
esac
问题
于是我天真地以为在前面的代码中用OPTIONS=( $(timew s :ids $(date -I -d'8 days ago') - $(date -I -d'tomorrow') | tac | head -n 34 | sed -ne 's:.*@::p' | sed -e 's|\s\+[0-9]\+:.*| |g' -e's:\s\+: ":' -e's:\s*$:":'))
代替就可以了。但似乎不会那么容易考虑报价。我试图以各种方式破解它,包括在 while read
循环中和使用 Shell parameter expansion: ${variable@Q},以及其他可怕的东西,但没有找到任何可行的方法。
问题
如何使用我的 Timewarrior 输出正确填充对话框选项?
这应该能达到你想要的效果:
#!/bin/bash
HEIGHT=15
WIDTH=40
CHOICE_HEIGHT=4
BACKTITLE="Backtitle here"
TITLE="Title here"
MENU="Choose one of the following options:"
generate_options(){
cat << EOF
Option 1
Option 2
Option 3
EOF
}
declare -a OPTIONS
count=1
while IFS= read -r line; do
OPTIONS+=( $((count++)) "$line" )
done < <(generate_options)
CHOICE=$(dialog --clear \
--backtitle "$BACKTITLE" \
--title "$TITLE" \
--menu "$MENU" \
$HEIGHT $WIDTH $CHOICE_HEIGHT \
"${OPTIONS[@]}" \
2>&1 >/dev/tty)
clear
case $CHOICE in
1)
echo "You chose Option 1"
;;
2)
echo "You chose Option 2"
;;
3)
echo "You chose Option 3"
;;
esac
您只需要将 cat
command 替换为您的命令(行首没有数字)。
所以这个问题的完整解决方案是:
#!/bin/bash
HEIGHT=40
WIDTH=80
CHOICE_HEIGHT=30
BACKTITLE="Timewarrior"
TITLE="Resume Selector"
MENU="Select task to resume"
generate_options(){
# events of the last week, filtered by $@
timew s :ids $(date -I -d'8 days ago') - $(date -I -d'tomorrow') "$@" |
# most recent first, keep only a 60 entry buffer
tac | head -n 60 |
# format the whole thing as '1 some labels' and so on
sed -ne 's:.*@::p' |
sed -e 's|\s\+[0-9]\+:.*| |g' -e's:^: :' |
# keep only 30 entries
uniq | head -n 30
}
declare -a OPTIONS
while IFS= read -r line; do
bid=$(echo "$line" | awk '{print }')
peg=$(echo "$line" | sed 's:[0-9]\+\ \+::')
# get ride of duplicates
case "${OPTIONS[@]}" in *"$peg"*) continue ;; esac
OPTIONS+=( "$bid" "$peg" )
done < <(generate_options "$@")
CHOICE=$(dialog --clear \
--backtitle "$BACKTITLE" \
--title "$TITLE" \
--menu "$MENU" \
$HEIGHT $WIDTH $CHOICE_HEIGHT \
"${OPTIONS[@]}" \
2>&1 >/dev/tty)
clear
if [[ -z $CHOICE ]] ; then
exit
fi
timew cont "@$CHOICE"
上下文
我正在尝试构建一个包含我的时间战士数据的对话框,这样我就可以直接 select 我要返回的内容而不是 timew s :ids filter_tag
,然后 time cont @12
.
因此,首先我创建了试图填充对话框选项的数据集:
timew s :ids $(date -I -d'8 days ago') - $(date -I -d'tomorrow') |
# most recent first, only the top 30 (4 additional lines are decoration)
tac | head -n 34 |
# format the whole thing as '1 "some label "' and so on
sed -ne 's:.*@::p' |
sed -e 's|\s\+[0-9]\+:.*| |g' -e's:\s\+: ":' -e's:\s*$:":' -e's:^: :'
这会生成如下所示的报告:
1 "some_info, some_info"
2 "some_info, some_info"
3 "some_info, some_info"
4 "some_info"
5 "some_info, some_info"
6 "some_info, some_info, some_info"
7 "some_info, some_info"
8 "some_info, some_info-some_info, some_info, some_info"
9 "some_info, some_info"
10 "some_info, some_info-some_info, some_info, some_info"
11 "some_info, some_info"
12 "some_info, some_info"
13 "some_info"
14 "some_info, some_info"
14 "some_info, some_info"
15 "some_info, some_info, some_info"
16 "some_info, some_info, some_info, some_info, some_info, some_info"
17 "some_info, some_info, some_info"
18 "some_info"
19 "some_info, some_info"
20 "some_info"
21 "some_info, some_info, some_info, some_info, some_info, some_info"
22 "some_info, some_info"
23 "some_info, some_info, some_info, some_info, some_info, some_info"
24 "some_info, some_info45, some_info some_info some_info, some_info"
25 "some_info"
26 "some_info"
27 "some_info, some_info, some_info"
28 "some_info, some_info, some_info, some_info"
29 "some_info, some_info, some_info"
30 "some_info"
对话框脚手架
所以我找到了这个脚手架
#!/bin/bash
HEIGHT=15
WIDTH=40
CHOICE_HEIGHT=4
BACKTITLE="Backtitle here"
TITLE="Title here"
MENU="Choose one of the following options:"
OPTIONS=(1 "Option 1"
2 "Option 2"
3 "Option 3")
CHOICE=$(dialog --clear \
--backtitle "$BACKTITLE" \
--title "$TITLE" \
--menu "$MENU" \
$HEIGHT $WIDTH $CHOICE_HEIGHT \
"${OPTIONS[@]}" \
2>&1 >/dev/tty)
clear
case $CHOICE in
1)
echo "You chose Option 1"
;;
2)
echo "You chose Option 2"
;;
3)
echo "You chose Option 3"
;;
esac
问题
于是我天真地以为在前面的代码中用OPTIONS=( $(timew s :ids $(date -I -d'8 days ago') - $(date -I -d'tomorrow') | tac | head -n 34 | sed -ne 's:.*@::p' | sed -e 's|\s\+[0-9]\+:.*| |g' -e's:\s\+: ":' -e's:\s*$:":'))
代替就可以了。但似乎不会那么容易考虑报价。我试图以各种方式破解它,包括在 while read
循环中和使用 Shell parameter expansion: ${variable@Q},以及其他可怕的东西,但没有找到任何可行的方法。
问题
如何使用我的 Timewarrior 输出正确填充对话框选项?
这应该能达到你想要的效果:
#!/bin/bash
HEIGHT=15
WIDTH=40
CHOICE_HEIGHT=4
BACKTITLE="Backtitle here"
TITLE="Title here"
MENU="Choose one of the following options:"
generate_options(){
cat << EOF
Option 1
Option 2
Option 3
EOF
}
declare -a OPTIONS
count=1
while IFS= read -r line; do
OPTIONS+=( $((count++)) "$line" )
done < <(generate_options)
CHOICE=$(dialog --clear \
--backtitle "$BACKTITLE" \
--title "$TITLE" \
--menu "$MENU" \
$HEIGHT $WIDTH $CHOICE_HEIGHT \
"${OPTIONS[@]}" \
2>&1 >/dev/tty)
clear
case $CHOICE in
1)
echo "You chose Option 1"
;;
2)
echo "You chose Option 2"
;;
3)
echo "You chose Option 3"
;;
esac
您只需要将 cat
command 替换为您的命令(行首没有数字)。
所以这个问题的完整解决方案是:
#!/bin/bash
HEIGHT=40
WIDTH=80
CHOICE_HEIGHT=30
BACKTITLE="Timewarrior"
TITLE="Resume Selector"
MENU="Select task to resume"
generate_options(){
# events of the last week, filtered by $@
timew s :ids $(date -I -d'8 days ago') - $(date -I -d'tomorrow') "$@" |
# most recent first, keep only a 60 entry buffer
tac | head -n 60 |
# format the whole thing as '1 some labels' and so on
sed -ne 's:.*@::p' |
sed -e 's|\s\+[0-9]\+:.*| |g' -e's:^: :' |
# keep only 30 entries
uniq | head -n 30
}
declare -a OPTIONS
while IFS= read -r line; do
bid=$(echo "$line" | awk '{print }')
peg=$(echo "$line" | sed 's:[0-9]\+\ \+::')
# get ride of duplicates
case "${OPTIONS[@]}" in *"$peg"*) continue ;; esac
OPTIONS+=( "$bid" "$peg" )
done < <(generate_options "$@")
CHOICE=$(dialog --clear \
--backtitle "$BACKTITLE" \
--title "$TITLE" \
--menu "$MENU" \
$HEIGHT $WIDTH $CHOICE_HEIGHT \
"${OPTIONS[@]}" \
2>&1 >/dev/tty)
clear
if [[ -z $CHOICE ]] ; then
exit
fi
timew cont "@$CHOICE"