LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1265|回复: 11

考考大家一道题

[复制链接]
发表于 2004-9-3 00:32:27 | 显示全部楼层 |阅读模式
如果一个目录tmpdir下有数十个文件如下:
more ls find ...

另外有一个文件list,内容如下:
# CONFIG_MORE is not set
# CONFIG_LS is not set
# CONFIG_FIND is not set
...

我想把文件list根据tmpdir目录下对应的文件名修改成:
CONFIG_MORE=y
CONFIG_LS=y
CONFIG_FIND=y
...

请问如何用sed来完成任务?

发表于 2004-9-3 08:56:02 | 显示全部楼层
[PHP]#!/bin/sh
sed 's/\#//g' list >> lista
sed 's/ is not set/\=y/g' lista >> listb
mv listb list;rm lista

[/PHP]
发表于 2004-9-3 09:19:23 | 显示全部楼层
sed `s'能够使用变量替换吗?

  1. #!/bin/sh
  2. target=$(sed -ne 's/# CONFIG_\([[:alpha:]]\+\) *is not set/\L\1/p' list)
  3. for file in $target
  4.         do if [ -f $file ]
  5.                 then echo "$file is to be substitute"
  6.         fi
  7. done
复制代码
 楼主| 发表于 2004-9-3 11:35:12 | 显示全部楼层
最初由 liqishan 发表
[PHP]#!/bin/sh
sed 's/\#//g' list >> lista
sed 's/ is not set/\=y/g' lista >> listb
mv listb list;rm lista

[/PHP]


嘿,我要的是根据目录tmpdir下的对应文件名来修改list。
比如说,tmpdir下有文件more,那么我就要让list里的
# CONFIG_MORE is not set换成 CONFIG_MORE=y,
而不是把所有的条目换成CONFIG_xxx=y!

如果是这样的话,那还不简单,呵呵。

to aaccdd,sed对于for提供的局部变量好像不感冒,会出错的。我就是为此而烦恼。相信用perl会更加好。
发表于 2004-9-3 11:48:00 | 显示全部楼层
我现在的想法是:
对list逐行过滤,
提取其中CONFIG_XXX等的XXX部分
判断在./目录下文件XXX是否存在,
如果存在,将该行替换为CONFIG_XXX=y,
然后在处理下一行

所用的例子包括

  1. ls ./
  2. find  list  ls  more  ping  test

  3. cat list
  4. # Auto generated by ./configure, don't edit!

  5. # CONFIG_MORE is not set
  6. # CONFIG_LS is not set
  7. # CONFIG_FIND is not set
  8. # CONFIG_RM is not set
  9. # CONFIG_MV is not set
  10. CONFIG_LIST=y

复制代码

实现上还搞不太清楚
知道的太少
 楼主| 发表于 2004-9-3 15:39:34 | 显示全部楼层
最好能做成一个函数。
mdfconfig [y/n] keyword

for的遍历变量总是不能被sed识别,苦恼。
发表于 2004-9-3 15:51:57 | 显示全部楼层
最初由 home_king 发表
最好能做成一个函数。
mdfconfig [y/n] keyword

for的遍历变量总是不能被sed识别,苦恼。

这样试试看
胡写的一个

  1. for i in !(list);do
  2.     [[ -f $i ]]&&var=$(echo $i|tr a-z A-Z)&&awk '/\<CONFIG_'"$var"'\>/{print $2,"=y"}' list
  3. #done >newlist
  4. done>tmp$$;rm list;mv tmp$$ list

复制代码
发表于 2004-9-3 16:58:35 | 显示全部楼层
我用awk拼凑了一个,
很乱,
不过好像我这里可以用
使用环境如上述

  1. ls *>file;awk '{line[NR]=($0)};END{for (i=1;i<=NR;i++){if (match(line[i],"CONFIG_") > 1) { if (match(line[i],"is not set") > 0){split(line[i],target," ");STR=(substr(target[2],8));str=tolower(STR);system( "if " "[ " "-f "str " ] ""; ""then"" echo ""CONFIG_"STR"=yes"";""fi" )  };continue};print line[i] }}' list>listnew;mv listnew list;rm file
复制代码
发表于 2004-9-3 17:17:19 | 显示全部楼层
运行前后比较:

  1. cat list
  2. # Auto generated by ./configure, don't edit!
  3. # CONFIG OPTIONS

  4. # CONFIG_MORE is not set
  5. # CONFIG_LS is not set
  6. # CONFIG_FIND is not set
  7. # CONFIG_RM is not set
  8. # CONFIG_MV is not set
  9. CONFIG_LIST=y

  10. cat list
  11. # Auto generated by ./configure, don't edit!
  12. # CONFIG OPTIONS

  13. CONFIG_MORE=yes
  14. CONFIG_LS=yes
  15. CONFIG_FIND=yes
  16. CONFIG_LIST=y
复制代码
 楼主| 发表于 2004-9-4 17:31:47 | 显示全部楼层
原来sed的引用变量的方法是为sed命令串加上双引号,让bash自行解析,为提高扩展性能,把修改键值的功能编写成函数。
给出我的脚本。


  1. #!/bin/sh

  2. # Set the specified keyword to value [y/n]
  3. setconfig(){
  4.     keyword=$2
  5.     value=$1
  6.     sed -e "s|^# \(CONFIG_$keyword\).*|\1=$value|" $configfile > tmpfile$$
  7.     [ $? -eq 0 ] && mv tmpfile$$ $configfile && return 0
  8.     rm -f tmpfile$$ && return 1
  9. }

  10. targetdir=$1
  11. configfile=$2

  12. # Maybe check the paras avaliablity first. I forget "test"'s syntax, please fix it.

  13. for i in $targetdir/*;do
  14.     i=$(awk -v i=${i##*/} 'BEGIN{print toupper(i)}')
  15.     setconfig y $i
  16. done

  17. setconfig n LOSETUP

复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表