读取文本行进行处理。这么难啊。

sh/bash/dash/ksh/zsh等Shell脚本
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙
送出感谢: 4 次
接收感谢: 256 次

读取文本行进行处理。这么难啊。

#1

帖子 eexpress » 2006-08-14 23:11

for i in tmp "Exec ${fvwm}root-关机" "Pick Destroy" Restart
可以处理空格。下划线部分是一个文件的4行内容。

for i in `awk '{printf(" \"%s\"",$0)}' auto-menu.ini`
就根本不能处理空格了。输出是一样的结果。放到变量line里面,数据一样的。
for i in $line
也不行。

网上只看到用一个递增的计数变量cnt,每次用awk数出第cnt行,用while处理的。

read的数组,使用*输出都不行。这for 循环太不好用了。
● 鸣学
头像
5451vs5451
帖子: 345
注册时间: 2006-07-14 18:56
来自: Apple Valley, Planet Tux, Linux System
送出感谢: 0
接收感谢: 0

#2

帖子 5451vs5451 » 2006-08-14 23:29

用awk里面的for呢?
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙
送出感谢: 4 次
接收感谢: 256 次

#3

帖子 eexpress » 2006-08-14 23:36

用awk简直就是万能的。但是,我的大量操作都是在bash哦。如果用awk,肯定需要另起一个awk的输入文件了。而且还是需要bash做一些事情。麻烦的哦。
● 鸣学
头像
laborer
帖子: 1016
注册时间: 2005-10-25 11:15
送出感谢: 0
接收感谢: 1 次
联系:

#4

帖子 laborer » 2006-08-15 0:30

嗯,bash的这种foreach的用法有时确实不是太好使,一般用下面这个方法凑合一下也行

代码: 全选

IFS='\n'
for i in `cat <<_EOF_
test test test
test test
test
_EOF_`; do
    echo $i
done

就是把分割符号定义为\n,不过如果是列文件名,而且文件名中包含回车,那也会很不爽,当然这种情况很少见。
hreiser@oakland:~$ killall -9 wife
police@oakland:~$ sudo find / -user hreiser
court@oakland:~$ sudo mv /home/hreiser /jail/
court@oakland:~$ sudo usermod -d /jail/hreiser -s "/usr/sbin/chroot /jail/" hreiser
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙
送出感谢: 4 次
接收感谢: 256 次

#5

帖子 eexpress » 2006-08-15 15:37

看过IFS,是3个分隔符号,没敢动,怕下面的恢复不对。你这样的在本bash里面不恢复了?
● 鸣学
头像
5451vs5451
帖子: 345
注册时间: 2006-07-14 18:56
来自: Apple Valley, Planet Tux, Linux System
送出感谢: 0
接收感谢: 0

#6

帖子 5451vs5451 » 2006-08-15 17:19

今天看到这种用法,跟awk很类似了。

代码: 全选

for ((i=1; i<3; i++)); do
    echo $i
done
头像
5451vs5451
帖子: 345
注册时间: 2006-07-14 18:56
来自: Apple Valley, Planet Tux, Linux System
送出感谢: 0
接收感谢: 0

#7

帖子 5451vs5451 » 2006-08-15 17:45

OLDIFS=$IFS
IFS='\n'
read -a lines -d _EOF_ < temp
echo ${lines[@]}
IFS=$OLDIFS
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙
送出感谢: 4 次
接收感谢: 256 次

#8

帖子 eexpress » 2006-08-15 18:36

新的bash都支持(())的写法。
read -a的也想过了。当时是想接受一行,然后lines[*]输出。就是觉得太难受。 :lol:
还用sed等都试过。就是不清楚为什么手动的写列表可以,而自动输出一样的数据的列表就不认。
● 鸣学
头像
5451vs5451
帖子: 345
注册时间: 2006-07-14 18:56
来自: Apple Valley, Planet Tux, Linux System
送出感谢: 0
接收感谢: 0

#9

帖子 5451vs5451 » 2006-08-15 20:09

关键是awk输出内容中引号就是引号,没有特殊意义。
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙
送出感谢: 4 次
接收感谢: 256 次

#10

帖子 eexpress » 2006-08-15 20:53

就是确定了bash解释文本信息(指手动写的)和命令输出的信息(``包括起来执行的结果)不同?
头天差点都用csh了的。
● 鸣学
头像
5451vs5451
帖子: 345
注册时间: 2006-07-14 18:56
来自: Apple Valley, Planet Tux, Linux System
送出感谢: 0
接收感谢: 0

#11

帖子 5451vs5451 » 2006-08-15 21:50

bash处理for i in `awk '{printf(" \"%s\"",$0)}' auto-menu.ini` 的时候,应该是先unquoting,然后调用awk,再对awk的输出做word splitting。所以awk输出的引号仅仅被当作普通文本处理。
头像
5451vs5451
帖子: 345
注册时间: 2006-07-14 18:56
来自: Apple Valley, Planet Tux, Linux System
送出感谢: 0
接收感谢: 0

#12

帖子 5451vs5451 » 2006-08-15 21:51

我是这么理解的:bash处理for i in `awk '{printf(" \"%s\"",$0)}' auto-menu.ini` 的时候,先unquoting,然后调用awk,再对awk的输出做word splitting。因为unquoting只进行一次,所以awk输出的引号仅仅被当作普通文本处理。
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙
送出感谢: 4 次
接收感谢: 256 次

#13

帖子 eexpress » 2006-08-15 23:18

再对awk的输出做word splitting

这样理解确实可能了。

line="tmp \"Exec \${fvwm}root-关机\" \"Pick Destroy\" Restart"
echo $line
for i in $line

这样都不行的。看来用for 是死路了。
● 鸣学
头像
5451vs5451
帖子: 345
注册时间: 2006-07-14 18:56
来自: Apple Valley, Planet Tux, Linux System
送出感谢: 0
接收感谢: 0

#14

帖子 5451vs5451 » 2006-08-16 12:17

exec 3<&0 0<auto-menu.ini
while read; do
...
done
exec 0<&3
或者
while read; do
...
done < auto-menu.ini
不过这两种方式把每一行的前导空格都截掉了。
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙
送出感谢: 4 次
接收感谢: 256 次

#15

帖子 eexpress » 2006-09-02 3:13

闲来无事的时候,用eval把这个完成了。eval里面包含了子程序而已。
● 鸣学
回复

回到 “Shell脚本”