Linux 如何在shell中重复破折号(连字符)

Linux 如何在shell中重复破折号(连字符),linux,bash,shell,repeat,Linux,Bash,Shell,Repeat,如何在shell中重复字符-n次?我已经阅读并尝试过,但这对-不起作用。它抛出错误无效选项。下面是我使用的确切命令: printf '-%.0s' {1..100} 原始发布行:printf'-%0.s'{1..100} 我还尝试通过放置一个\来转义-,但在这种情况下,它会重复\-n次。这会引发一个错误: $ printf '-%.0s' {1..100}; echo "" bash: printf: -%: invalid option printf: usage: printf [-v v

如何在shell中重复字符
-
n次?我已经阅读并尝试过,但这对
-
不起作用。它抛出错误
无效选项
。下面是我使用的确切命令:

printf '-%.0s' {1..100}
原始发布行:
printf'-%0.s'{1..100}

我还尝试通过放置一个
\
来转义
-
,但在这种情况下,它会重复
\-
n次。

这会引发一个错误:

$ printf '-%.0s' {1..100}; echo ""
bash: printf: -%: invalid option
printf: usage: printf [-v var] format [arguments]
这在
bash
下可以正常工作:

$ printf -- '-%.0s' {1..100}; echo ""
----------------------------------------------------------------------------------------------------
printf '%.0s-' {1..100}
对于其他壳,请尝试:

printf -- '-%.0s' $(seq 100); echo ""

问题在于
printf
期望
-
启动一个选项。在这种情况下,Unix/POSIX实用程序中很常见,
--
printf
发送信号,不需要更多选项

对循环和数字范围使用

for i in {1..10}; 
    do echo "-"; 
done
或者在一行上:

for i in {1..10}; 
    do echo -n "-"; 
done
输出<代码>------------


EDIT:这是在您的
printf
编辑之前。

我建议使用传统的
for
循环,因为不需要生成子进程或扩展100个参数:

N=100
for((i = 0; i < $N; ++i)); do
  printf -
done
N=100
对于((i=0;i<$N;++i));做
printf-
完成
奇怪的是,
printf-%s
会触发“无效选项”,但
printf-
不会。为了更加安全,您可以执行
printf%s-

提供了一个通用解决方案,该解决方案显示了如何消除所有类似POSIX的实用程序的操作数选项的歧义

在本例中,最简单的解决方案是(不仅适用于
bash
,而且适用于
ksh
zsh
):

%.0s
放在
-
之前可以避免将初始
-
误认为选项的问题

略微优化:[1]


[1]
%.0s
实际上是最可移植的形式(要完全可移植,还必须避免大括号扩展,
{…}
)。
%.s
是一种等效的速记形式,受
bash
ksh
dash
支持,但不受
zsh
  • jot
    可以做到这一点,不带任何羞耻感:

  • seq也一样,但也不一样,它需要一个
    tr

    seq -s- 100 | tr -d '[0-9]'
    

  • 您还可以使用
    tput
    printf
    来完成用确切数量的破折号填充终端,或者直接画线,或者将破折号线写入变量(例如
    line
    ),以便重复使用,例如,将屏幕宽度的破折号线写入变量
    line
    ,你可以做:

    $ eval printf -v line '%.0s-' {1..$(tput cols)}
    
    然后每次需要画线时,只需
    回显“$line”
    。您还可以使用将其直接写入屏幕

    $ eval printf '%.0s-' {1..$(tput cols)}
    

    (我不是
    eval
    的超级粉丝,但这是一个可以保证命令结果不会有害的用途)。

    这是我多年来的目标。。。但对AIX不友好。更改最后一个字符以更改组成该行的重复字符

    printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' _
    

    +1.这个解决方案值得记住,因为它不是printf特有的;许多实用程序支持将
    --
    作为一个特殊标志,表示“在这一点之后没有更多选项”。不仅仅是Linux实用程序,它是POSIX指定的实用程序约定。参见@CharlesDuffy Very good中的准则10。更新了答案以提及POSIX。我检查了,因为它不接受任何选项,所以它没有提到接受
    --
    。事实上。这就是说,POSIX的实用程序指南部分指出,与指南的偏差将在实用程序的单独文档的选项部分进行描述。
    echo-n
    显然是非POSIX指定的行为。如果你想随身携带,你可能会远离它。请参阅:“如果第一个操作数为-n,或者如果任何操作数包含反斜杠(“\”)字符,则结果由实现定义”感谢提示!出于这个原因,
    printf
    是更好的选择吗?是的。(请参阅前面链接中的应用程序使用部分)
    -
    是一个完全有效的参数,通常用于根据上下文引用stdin或stdout,而
    -x
    设置一个选项标志。在算术求值中不需要
    $
    for((i=0;i
    printf'.s-'{1..100}
    不涉及子shell,因为大括号扩展是一个shell功能,
    printf
    是一个Bash内置函数。因此,将大括号扩展与内置函数
    printf
    相结合不受最大命令行长度的限制,但您是对的,在重复次数较多的情况下,有一些替代方法更快,尤其是更快内存效率高(但shell循环不是用于大量重复计数的正确工具)-参见。@mklement0确实,我在考虑涉及子进程批评的
    perl
    tr
    head
    等解决方案。如果
    printf
    不是内置的,那么我发布的解决方案将产生100个进程!是的,我对使用
    {1..N}
    的批评是它需要O(N)空格。事实上,
    {1..N}
    实际上需要Ω(N log N)空格,因为每个参数的大小都是以对数方式增加的……标题是“破折号”,但它的标签是“bash”。你指的是哪一个?@Kusalananda:OP指的是破折号字符(
    -
    ,ASCII/Unicode码点
    0x2d
    )。(严格来说,字符的名称是连字符,但实际上这两个名称可以互换使用。)@mklement0啊。我这方面有严重的误解。我最近读了太多语言严重混乱的问题……因为
    jot
    不是POSIX指定的工具,它可以说和bash一样不可移植。同样的批评也适用于
    seq
    @CharlesDuffy,没错……但是OP中没有POSIX标记。如果,正如你所说的那样注释,zsh和GNU printf(至少)失败(当时
    $ eval printf '%.0s-' {1..$(tput cols)}
    
    printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' _