Bash同时输入if和else语句

Bash同时输入if和else语句,bash,Bash,这里是上下文:我正在制作一个小的Linux命令,以便在创建C程序时自动创建基本代码。 我的命令名为ctouch:它类似于touch命令,但在创建文件后,它还创建了C程序的基本结构: #include <stdio.h> #include <stdlib.h> int main(){ return 0: } #包括 #包括 int main(){ 返回0: } 附加这些行是有效的。这是我的密码: #! /bin/bash for arg in "$@"

这里是上下文:我正在制作一个小的Linux命令,以便在创建C程序时自动创建基本代码。 我的命令名为
ctouch
:它类似于
touch
命令,但在创建文件后,它还创建了C程序的基本结构:

#include <stdio.h>
#include <stdlib.h>

int main(){



    return 0:
}
#包括
#包括
int main(){
返回0:
}
附加这些行是有效的。这是我的密码:

#! /bin/bash

for arg in "$@"
do
    [ ${arg: -2} == ".c" ] && touch "$arg" || touch "$arg.c"

    echo '#include <stdio.h>' > "$arg"
    echo '#include <stdlib.h>' >> "$arg"
    echo $'\nint main90{\n\n\t' >> "$arg"
    echo $'\n\treturn 0;\n\n}' >> "$arg"
done
#/bin/bash
对于“$@”中的arg
做
[${arg:-2}=“.c”]&触摸“$arg”| |触摸“$arg.c”
echo“#include”>“$arg”
echo“#include”>>“$arg”
echo$'\nIT main90{\n\n\t'>>“$arg”
echo$'\n\t返回0;\n\n}'>>“$arg”
完成
如您所见,它可以创建的文件数量与
touch
可以获取的参数数量相同。如果我忘了指定
.c
扩展名,条件循环(do后面的一行)很有用:但问题是当参数不是以
.c
结尾时,
if
else
都会执行,但如果我没有“忘记”指定它是一个c文件,则可以


我怎样才能解决这个问题呢?

它不会同时占用两个分支。它会根据扩展名进行
触摸
,但如果您输入的是扩展名,则
echo
序列会将其输出放在没有扩展名的文件中

我将重构为使用
案例
,使用a打印多行,并完全跳过
触摸
;但最简单的解决方法是,如果输出文件缺少扩展名,只需更改输出文件名

for arg in "$@"
do
    case $arg in
      *.c) ;;
      *) arg="$arg.c";;
    esac

    cat <<'____HERE' > "$arg"
#include <stdio.h>
#include <stdlib.h>

int main(){




    return 0;
}
____HERE
done
“$@中的参数的
”
做
案例$arg in
*(c);;
*)arg=“$arg.c”;;
以撒

cat与此处文件的备选方案:

for arg in "$@"; do
    if [ "${arg: -2}" == ".c" ]; then
        filename="$arg"
    else
        filename="${arg}.c"
    fi

cat<<EOT >"$filename"
#include <stdio.h>
#include <stdlib.h>

int main() {


    return 0;
}
EOT

done
“$@”中arg的
;做
如果[“${arg:-2}”==“.c”];然后
filename=“$arg”
其他的
filename=“${arg}.c”
fi
cat有一点变化:

#! /bin/bash

for arg in "$@"
do
     [[ ${arg: -2} == ".c" ]] && FILE="$arg" || FILE="$arg.c"
    echo '#include <stdio.h>' > "$FILE"
    echo '#include <stdlib.h>' >> "$FILE"
    echo $'\nint main90{\n\n\t' >> "$FILE"
    echo $'\n\treturn 0;\n\n}' >> "$FILE"
done
#/bin/bash
对于“$@”中的arg
做
[[${arg:-2}=>.c”]&&FILE=“$arg”| | FILE=“$arg.c”
echo“#include”>“$FILE”
echo“#include”>>“$FILE”
echo$'\n在main90{\n\n\t'>>“$FILE”
echo$'\n\t返回0;\n\n}'>>“$FILE”
完成

简化的解决方案避免了对条件的任何需要。无论原始参数是否以
.c
结尾,您都希望创建一个
.c
文件,如果该文件不存在,则有效地添加它。这与总是将其添加到尝试删除它的结果中是一样的。您也不需要使用
touch
显式创建文件;如果需要,输出重定向将创建文件

这还演示了将模板内容写入文件的另一种方法

for arg in "$@"
do
  {
    printf '#include <stdio.h>\n'
    printf '#include <stdlib.h>\n'
    printf '\nint main90 {\n'
    printf '\n\treturn 0;\n\n}\n'  # end with a newline
  } > "${arg%.c}.c"
done
“$@中的参数的
”
做
{
printf'#包括\n'
printf'#包括\n'
printf'\n在main90{\n'
printf'\n\t返回0;\n\n}\n'#以换行结束
}>“${arg%.c}.c”
完成

请注意,您的文件可能应该是一个正确的POSIX文本文件,以换行符结尾。

如果
$arg
不包含
.c
,您将创建一个名为
$arg.c
的文件。稍后在脚本中,您将写入
$arg
,但我们刚刚确定
$arg
不包含
.c
,因此您将使用该重定向写入非
.c
文件。但是,我怀疑当您的
$arg
包含
.c
时,此脚本工作正常。请注意
条件&&cmd1 | | cmd2
并不完全等同于
if条件then cmd1;else-cmd2;fi
–如果
cmd1
失败,将执行
cmd2
!(请参阅)您可以用一个
bash
ism替换另一个更清晰的:
if[[$arg==*.c]];然后触摸“$arg”;或者点击“$arg.c”
。您也可以完全省去测试,使用POSIX兼容的参数扩展:
arg=${arg%.c}.c
。如果有此条
.c
,则无论它是否在最初的位置,都会将其放回原处。您好,谢谢您的回答。你能解释一下这只猫的。。。等等,是什么意思?或者你能给我一个解释它的链接吗?可能是因为heredoc更容易阅读和书写(以及更改)。实际上我使用的是
printf
,而不是heredoc,但有人认为他们可以“改进”我的答案。不管怎样,
echo
都有一些令人讨厌的可移植性问题;无论是
printf
还是
cat
here文档都会优雅地避免这些内容。我最初发布的
printf
答案使选项卡等变得清晰;但是一个在正确位置有标签的here文档也可以很好地工作(只是不能象征性地显示标签的位置),所以我将@JohnKugelman留下编辑。我最初的答案只有一个
printf
,所以你也可以去掉大括号。(这比我以前盲目复制/粘贴OP的代码要优雅得多。)我曾玩弄过,但它会变得丑陋,除非你使用一个行数组,在这种情况下,你最好接受使用你使用的here文档运行
cat
的成本。