ico*_*ast 7 sed awk text-processing columns
有没有比使用sed
and更快速地获得几列值的方法awk
?
举例来说,如果我有输出ls -hal /
,我只想获取文件和目录名称和大小,我怎么能轻易和迅速地这样做,而不必花费几分钟的时间调整我的命令。
total 16078
drwxr-xr-x 33 root wheel 1.2K Aug 13 16:57 .
drwxr-xr-x 33 root wheel 1.2K Aug 13 16:57 ..
-rw-rw-r-- 1 root admin 15K Aug 14 00:41 .DS_Store
d--x--x--x 8 root wheel 272B Jun 20 16:40 .DocumentRevisions-V100
drwxr-xr-x+ 3 root wheel 102B Mar 27 12:26 .MobileBackups
drwx------ 5 root wheel 170B Jun 20 15:56 .Spotlight-V100
d-wx-wx-wt 2 root wheel 68B Mar 27 12:26 .Trashes
drwxrwxrwx 4 root wheel 136B Mar 30 20:00 .bzvol
srwxrwxrwx 1 root wheel 0B Aug 13 16:57 .dbfseventsd
---------- 1 root admin 0B Aug 16 2012 .file
drwx------ 1275 root wheel 42K Aug 14 00:05 .fseventsd
drwxr-xr-x@ 2 root wheel 68B Jun 20 2012 .vol
drwxrwxr-x+ 289 root admin 9.6K Aug 13 10:29 Applications
drwxrwxr-x 7 root admin 238B Mar 5 20:47 Developer
drwxr-xr-x+ 69 root wheel 2.3K Aug 12 21:36 Library
drwxr-xr-x@ 2 root wheel 68B Aug 16 2012 Network
drwxr-xr-x+ 4 root wheel 136B Mar 27 12:17 System
drwxr-xr-x 6 root admin 204B Mar 27 12:22 Users
drwxrwxrwt@ 6 root admin 204B Aug 13 23:57 Volumes
drwxr-xr-x@ 39 root wheel 1.3K Jun 20 15:54 bin
drwxrwxr-t@ 2 root admin 68B Aug 16 2012 cores
dr-xr-xr-x 3 root wheel 4.8K Jul 6 13:08 dev
lrwxr-xr-x@ 1 root wheel 11B Mar 27 12:09 etc -> private/etc
dr-xr-xr-x 2 root wheel 1B Aug 12 21:41 home
-rw-r--r--@ 1 root wheel 7.8M May 1 20:57 mach_kernel
dr-xr-xr-x 2 root wheel 1B Aug 12 21:41 net
drwxr-xr-x@ 6 root wheel 204B Mar 27 12:22 private
drwxr-xr-x@ 68 root wheel 2.3K Jun 20 15:54 sbin
lrwxr-xr-x@ 1 root wheel 11B Mar 27 12:09 tmp -> private/tmp
drwxr-xr-x@ 13 root wheel 442B Mar 29 23:32 usr
lrwxr-xr-x@ 1 root wheel 11B Mar 27 12:09 var -> private/var
Run Code Online (Sandbox Code Playgroud)
我意识到有无数的选择ls
,我可能可以用这种方式为这个特定的例子做,但这是一个普遍的问题,我想要一个通用的解决方案来轻松快速地获取特定的列。
cut
不会削减它,因为它不需要正则表达式,而且我几乎从来没有遇到过用单个空格分隔列的情况。如果它可以工作,这将是完美的:
ls -hal / | cut -d'\s' -f5,9
Run Code Online (Sandbox Code Playgroud)
awk
并且sed
比我想要的更通用,基本上是整个语言。我不反对他们,只是除非我最近和他们一起做了很多事情,否则需要相当大的心理转变才能开始按照他们的方式思考并写出有效的东西。我通常正在思考我正在尝试解决的其他一些问题,突然不得不解决一个sed
/awk
问题,这让我失去了注意力。
有没有灵活的捷径来实现我想要的?
ric*_*ici 12
我不知道为什么
ls -hal / | awk '{print $5, $9}'
Run Code Online (Sandbox Code Playgroud)
在你看来,你的思维过程比
ls -hal / | cut -d'\s' -f5,9
Run Code Online (Sandbox Code Playgroud)
本来会,如果它有效。你真的要写下来吗?awk
在添加{}
变得自动之前只需要几行。(对我来说,最困难的问题是记住哪个字段编号对应于哪个数据,但也许您没有那个问题。)
您不必使用awk 的所有功能;为了简单地输出特定的列,你需要知道很少的 awk。
如果您想输出符号链接以及文件名,或者您的文件名中可能有空格,那么令人恼火的问题就是。(或者,更糟糕的是,换行符)。使用假设的 regex-aware cut,这不是问题(换行符除外);您只需替换-f5,9
为-f5,9-
. 但是,“字段 9 到最后”没有 awk 语法,您必须记住如何编写 for 循环。
这是一个小 shell 脚本,它将cut
-style-f
选项转换为 awk 程序,然后运行 awk 程序。它需要更好的错误检查,但它似乎有效。(额外的好处:-d
通过将选项传递给 awk 程序来处理选项。)
#!/bin/bash
prog=\{
while getopts f:d: opt; do
case $opt in
f) IFS=, read -ra fields <<<"$OPTARG"
for field in "${fields[@]}"; do
case $field in
*-*) low=${field%-*}; high=${field#*-}
if [[ -z $low ]]; then low=1; fi
if [[ -z $high ]]; then high=NF; fi
;;
"") ;;
*) low=$field; high=$field ;;
esac
if [[ $low == $high ]]; then
prog+='printf "%s ", $'$low';'
else
prog+='for (i='$low';i<='$high';++i) printf "%s ", $i;'
fi
done
prog+='printf "\n"}'
;;
d) sep="-F$OPTARG";;
*) exit 1;;
esac
done
if [[ -n $sep ]]; then
awk "$sep" "$prog"
else
awk "$prog"
fi
Run Code Online (Sandbox Code Playgroud)
快速测试:
$ ls -hal / | ./cut.sh -f5,9-
7.0K bin
5.0K boot
4.2K dev
9.0K etc
1.0K home
8.0K host
33 initrd.img -> /boot/initrd.img-3.2.0-51-generic
33 initrd.img.old -> /boot/initrd.img-3.2.0-49-generic
...
Run Code Online (Sandbox Code Playgroud)