【问题标题】:Don't field separate when a field separator is found inside of quotes在引号内找到字段分隔符时不要进行字段分隔
【发布时间】:2021-04-19 10:51:32
【问题描述】:

我有这个命令的输出ls -lhp --group-directories-first:

drwxrwxr-x 2 aName aName 4.0K Jan 11 18:46  Desktop/
drwxr-xr-x 3 aName aName 4.0K Jan 13 16:43  Documents/
drwxr-xr-x 2 aName aName 4.0K Jan 12 18:47  Downloads/
drwxr-xr-x 2 aName aName 4.0K Jan 11 16:08  Music/
-rw-rw-r-- 1 aName aName 4.6M Jan 14 11:28 '2021-01-14 11-28-39.mov'
-rw-rw-r-- 1 aName aName 2.2M Jan 14 11:55 '2021-01-14 11-55-20.mkv'

我只想要这个:

Desktop/ 4.0K
Documents/ 4.0K
Downloads/ 4.0K
Music/ 4.0K
'2021-01-14 11-28-39.mov' 4.6M
'2021-01-14 11-55-20.mkv' 2.2M

所以我可以awk 仅用于第 9 列和第 5 列:

ls -lhp --group-directories-first | awk -F' ' '{print $9 " " $5}'

但是当文件名包含空格时,它的字段会分开,空格后面的所有内容都会丢失。

感谢您的智慧和时间!

【问题讨论】:

  • 考虑du -sh *
  • 哇。整洁的!除了这不会让我从文件中看到目录,并且可能比 ls 慢很多
  • 或者,awk 'BEGIN{FPAT="[^[:space:]'"'"']+|'"'"'[^'"'"']+'"'"'"} {print $9" "$5}'
  • 这太疯狂了@WiktorStribiżew,介意做出回应解释它是如何工作的,我会给你解决方案?

标签: shell awk sed ls


【解决方案1】:

只需使用正确的选项:

ls -1shp --group-directories-first

-s 列出大小和-1,每行一个条目。

如果您要求文件名之后的大小计数,请将其通过管道传送到 awk '{$(NF+1)=$1; $1=""}1。

【讨论】:

  • 很好,我必须 sed 删除 Total 行:ls -1shp --group-directories-first | sed 1d | awk '{$(NF+1)=$1; $1=""}1' 在同一个 awk 调用中删除该行更好吗?
  • @aName 不是更好,只是更优雅 IMO:awk '{$(NF+1)=$1;$1=""}NR>1'。
  • 我正在尝试在whiptail 中使用它,但whiptail 也将每个空格都视为一个字段,因此我需要以某种方式将文件名和大小作为独立字段提供给它
  • @aName 这似乎是一个不同的问题。一方面,我不知道 Whiptail 是如何工作的,这样我才能编写一个合适的解决方案。
【解决方案2】:

使用 find 和 printf:

find . -maxdepth 1 -printf "'%f' %k\n"

打印用单引号括起来的文件名 %f 以及文件/目录的 1k 块大小 (%k)

【讨论】:

    【解决方案3】:

    您需要设置正确的分隔符,并且使用 GNU awk,您可以使用 FPAT 正确分隔可能用单引号括起来的空格分隔字段:

    ls -lhp --group-directories-first | \
      awk 'BEGIN{FPAT="[^[:space:]'"'"']+|'"'"'[^'"'"']+'"'"'"} {print $9" "$5}'
    

    引号看起来很乱,但这正是字符串连接的工作原理,您只需将'...' 或"..." 并排放置,模式实际上是[^[:space:]']+|'[^']+' 并且匹配

    • [^[:space:]']+ - 除空格和' 之外的一个或多个字符
    • | - 或
    • '[^']+' - ',除了' 之外的一个或多个字符,然后是' 字符。

    见online demo:

    s="drwxrwxr-x 2 aName aName 4.0K Jan 11 18:46  Desktop/
    drwxr-xr-x 3 aName aName 4.0K Jan 13 16:43  Documents/
    drwxr-xr-x 2 aName aName 4.0K Jan 12 18:47  Downloads/
    drwxr-xr-x 2 aName aName 4.0K Jan 11 16:08  Music/
    w-rw-r--> -rw-rw-r-- 1 aName aName 4.6M Jan 14 11:28 '2021-01-14 11-28-39.mov'
    -rw-rw-r-- 1 aName aName 2.2M Jan 14 11:55 '2021-01-14 11-55-20.mkv'"
     awk 'BEGIN{FPAT="[^[:space:]'"'"']+|'"'"'[^'"'"']+'"'"'"} {print $9" "$5}' <<< "$s"
    

    输出:

    Desktop/ 4.0K
    Documents/ 4.0K
    Downloads/ 4.0K
    Music/ 4.0K
    11:28 aName
    '2021-01-14 11-55-20.mkv' 2.2M
    

    【讨论】:

    • 我不知道为什么,但是在我的终端ls -lhp | awk 'BEGIN{FPAT="[^[:space:]'"'"']+|'"'"'[^'"'"']+'"'"'"} {print $9" "$5}' 仍然输出类似2021-01-14 4.6M 的东西(注意空格后面的文件名已被切断)
    • @aName 抱歉,您可能没有 GNU awk。
    • @aName 或者,您的字符串与您在问题中显示的不同。
    【解决方案4】:

    你可以试试这个awk

     ls -lhp --group-directories-first | awk -F' ' 'NR <= 4 {print $9, $5} NR > 4 {print $9,$10, $5}'
    
    result:
    
    Desktop/ 4.0K
    Documents/ 4.0K
    Downloads/ 4.0K
    Music/ 4.0K
    '2021-01-14 11-28-39.mov' 4.6M
    '2021-01-14 11-55-20.mkv' 2.2M
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-14
      • 1970-01-01
      • 2022-09-29
      • 1970-01-01
      • 2022-11-24
      • 2016-01-23
      • 2015-08-02
      • 2017-07-05
      相关资源
      最近更新 更多