AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / ubuntu / 问题 / 1181597
Accepted
DK Bose
DK Bose
Asked: 2019-10-18 03:42:18 +0800 CST2019-10-18 03:42:18 +0800 CST 2019-10-18 03:42:18 +0800 CST

使用数组的 for 循环是否比在简单变量上使用字段拆分更好?

  • 772

我打开了几个应用程序。运行wmctrl并将输出通过管道传输到awk会列出窗口 ID(不包括“粘性”窗口),如下所示:

$ wmctrl -l | awk ' !/-1/ { print $1 } '
0x00a00018
0x04800005
0x04e00005
0x04400003
0x05000003
0x0540002b
0x05a00012
0x05800002
0x05c00003
$ 

我可以将此输出发送到wmctrl以关闭所有这些窗口:

  • 没有需要保存内容的窗口和不需要响应的窗口将在不询问我的情况下关闭,但是

  • 诸如具有未保存内容的编辑器或运行进程的终端之类的窗口将“优雅地”关闭:相应的应用程序将显示一个窗口,允许我保存更改或放弃更改或通知我仍在运行的进程。

分配给合适快捷方式的以下脚本有效:

#!/bin/bash

list=$(wmctrl -l | awk ' !/-1/ { print $1 } ')

for i in ${list[@]}
do
    wmctrl -i -a $i
    wmctrl -i -c $i
done

我发现更简单的(对我来说)for i in $list也有效。

有什么理由更喜欢其中一个吗?


“粘”和“优雅”是来自 的术语man wmctrl。

scripts bash
  • 4 4 个回答
  • 1835 Views

4 个回答

  • Voted
  1. Best Answer
    pLumo
    2019-10-18T04:00:14+08:002019-10-18T04:00:14+08:00

    在您的脚本$list中与${list[@]}.

    后者是数组语法,但在您的脚本中它是一个普通变量。


    由于您的wmctl输出项中没有空格,因此您不需要数组,并且使用$list非常好。


    如果它是一个数组,则$list只会是数组的第一项 (=> item1) ${list[@]}并将扩展到所有项 (=> item1 item2 item3)。

    但是,如果它实际上是一个数组,那么您真正想要的是"${list[@]}"(带引号)延伸到"item1" "item2" "item3",因此它不会因空白而窒息。


    (阅读)

    • 13
  2. steeldriver
    2019-10-18T04:28:35+08:002019-10-18T04:28:35+08:00

    循环通常while比for循环更适合处理命令输出,允许您直接处理行而不是将它们存储在列表或数组中。

    在这种情况下,它允许您完全避免该awk命令:

    wmctrl -l | while read -r id dt stuff; do 
      case $dt in 
        -1) continue
            ;; 
         *) echo wmctrl -i -a "$id"
            echo wmctrl -i -c "$id"
            ;; 
      esac
    done
    

    echo一旦你对它做正确的事情感到高兴,就删除s。

    如评论中所述,xargs是另一种选择-但是当您想对每个arg.

    • 7
  3. WinEunuuchs2Unix
    2019-10-18T03:51:10+08:002019-10-18T03:51:10+08:00

    回复原标题

    原标题问“什么类型的for循环比较好”。

    对我自己来说,最好的方法是最快的。要找出将time命令添加到您的脚本或函数。一些例子:

    $ time du -s
    
    real    0m0.002s
    user    0m0.003s
    sys     0m0.000s
    
    $ time ls
    
    real    0m0.004s
    user    0m0.000s
    sys     0m0.004s
    

    但是,在测试之间刷新缓存缓冲区很重要:

    • 在 Lubuntu 中删除缓存的正确方法是什么?

    如果两个循环的速度大致相同,我会选择可读性最好的一个。

    这个问题的范围是使速度无关紧要,因为大部分时间都花在等待用户输入上,而且大多数人最多只能打开 10 个窗口。


    对问题主体的回答

    其他答案集中在重写脚本上,所以我也会付出我的两分钱。

    该行:

    list=$(wmctrl -l | awk ' !/-1/ { print $1 } ')
    
    • 如果意图是一个数组,则格式错误
    • list是通用的而不是描述性的

    所以我会使用:

    Windows=( $(wmctrl -l | awk ' !/-1/ { print $1 } ') )
    
    • () 的外部集合告诉 bash/shell 内部的所有内容都是由空格分隔的数组元素。
    • Windows 就是我们所说的,所以它是一个描述性的数组名称。
    • Windows 是复数形式,因此命名约定有助于识别它是一个数组。

    该行:

    wmctrl -i -a $i
    
    • -i并且-a可以组合成-ia.
    • $i是非描述性的,我会$Window改用。

    有两种方法可以编写更短且更易读的脚本,第一种是使用数组:

    #!/bin/bash
    Windows=( $(wmctrl -l | awk ' !/-1/ { print $1 } ' ) )
    for Window in "${Windows[@]}" ; do wmctrl -ia $Window -c $Window ; done
    

    第二个没有数组:

    #!/bin/bash
    Windows=$(wmctrl -l | awk ' !/-1/ { print $1 } ' )
    for Window in $Windows ; do wmctrl -ia $Window -c $Window ; done
    

    我更喜欢数组方法,因为我正在尝试更多地了解它们并希望尽可能多地使用它们。然而,选择是你的。

    • 5
  4. user986805
    2019-10-19T02:59:38+08:002019-10-19T02:59:38+08:00

    您可以在没有阵列的情况下进行管理。将IFS设置为换行符将允许for循环行,然后您可以unset在循环内的 IFS 而不会影响循环本身。

    #!/bin/bash
    
    IFS=$'\n'
    for i in $(wmctrl -l); do
        unset IFS
        set -- $i
        (($2 > -1)) && wmctrl -i -a $1 -c $1
    done
    

    (重置位置参数是将一行拆分为字段的巧妙技巧)。

    如果您需要使用数组,您可以使用mapfile并利用回调函数创建类似于循环的内容。对于一小组迭代,使用更简单的函数调用可能是一个优势。

    mapfile -c 1 -C 'f(){ set -- $@; (($3 >= 0)) && wmctrl -i -a $2 -c $2; }; f' -t < <(wmctrl -l)
    

    (长版):

    #!/bin/bash
    
    f(){
        set -- $@
        if (($3 > -1)); then
            wmctrl -i -a $2 -c $2
        fi
    }
    mapfile -c 1 -C f -t < <(wmctrl -l)
    
    • 5

相关问题

  • 如何每 5 秒运行一次脚本?

  • 如何将必须从其自己的目录中运行的程序添加到面板或主菜单?

  • 如何编写 shell 脚本来安装应用程序列表?

  • Mac OS X Automator 的替代品?

  • 备份 bash 脚本未压缩其 tarball

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何运行 .sh 脚本?

    • 16 个回答
  • Marko Smith

    如何安装 .tar.gz(或 .tar.bz2)文件?

    • 14 个回答
  • Marko Smith

    如何列出所有已安装的软件包

    • 24 个回答
  • Marko Smith

    无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗?

    • 25 个回答
  • Martin Hope
    Flimm 如何在没有 sudo 的情况下使用 docker? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    Ivan 如何列出所有已安装的软件包 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    La Ode Adam Saputra 无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗? 2010-11-30 18:12:48 +0800 CST
  • Martin Hope
    David Barry 如何从命令行确定目录(文件夹)的总大小? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher “以下软件包已被保留:”为什么以及如何解决? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford 如何删除 PPA? 2010-07-30 01:09:42 +0800 CST

热门标签

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve