shell问答

sh/bash/dash/ksh/zsh等Shell脚本
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

shell问答

#1

帖子 oneleaf » 2005-07-30 9:43

1:从文件中抽取字段

有一个文件,如下,以空格分成3段(每段是7行),我现在想这样从里面抽取数据,如果某段中含有字段“REPORT COUNT= 22985”(如果含有的话,肯定是在这段的第6行中含有),则把这一段数据都放到一个新文件中,该如何实现呢?

有一个文件,如下,以空格分成3段(每段是7行),我现在想这样从里面抽取数据,如果某段中含有字段“REPORT COUNT= 22985”(如果含有的话,肯定是在这段的第6行中含有),则把这一段数据都放到一个新文件中,该如何实现呢??

代码: 全选

YTCMSC01      AMA112 MAR07 15:19:01 2900 INFO LONG DURATION CALL
           ORIG= CDMA_CPS 000000
           TERM=
           CLG NO= 13355356234
           CLD NO=                              $
           CONNECT TIME= 066/1426170  REPORT COUNT= 22986
           ANSWERED= Y

YTCMSC01      AMA112 MAR07 15:19:01 2800 INFO LONG DURATION CALL
           ORIG= CKT     YTIGW1TRKE  477
           TERM= CKT    SB0014VOICE  121
           CLG NO= 13854829695
           CLD NO=                    13361321136
           CONNECT TIME= 066/1435147  REPORT COUNT= 22985
           ANSWERED= Y

YTCMSC01      AMA112 MAR07 15:19:01 2700 INFO LONG DURATION CALL
           ORIG= CDMA_CPS 000000
           TERM=
           CLG NO= 13356916813
           CLD NO=                              $
           CONNECT TIME= 066/0849074  REPORT COUNT= 22984
           ANSWERED= Y

解决办法:
1.grep 'REPORT COUNT= 22985' -B5 -C1 youfile >newfile
2.cat $scr_file|awk 'BEGIN~/REPORT COUNT= 22985/ &print >'$dest_file'}'
3.awk 'BEGIN/REPORT COUNT= 22985/{print >"newfile"}' file
4.awk ' { for (i=7;i>0;i--);a[1]=;if (a[2]~/REPORT COUNT= 22986/){for (i=7;i>0;i--){print a[i]}}}' yourfile >newfile
上次由 oneleaf 在 2005-08-06 11:33,总共编辑 1 次。
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

2:如何删除最后一行

#2

帖子 oneleaf » 2005-07-30 9:44

如何删除文件的最后一行,我收集了6种方法,如:sed -i '$d' file

删除文件最后一行
1. tail -n 1 file
2. tail -1 filename
3. sed -n '$p' filename
4. "awk 'END ' file "
5.
ed file<$ d
.
w
!
6. sed -i '$d' file
(注:方法1234都没有对原文件进行修改)
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

删除文件的第n行和倒数第n行

#3

帖子 oneleaf » 2005-07-30 9:44

用sed和awk都可方便的实现

1.
删除第三行,并把结果送至文件newfile
sed '3d' file>newfile
删除倒数第三行,把结果送至文件newfile
tac file|sed '3d'|tac >newfile
2.
FILENAME="test"
N=2
#删除第N行
sed $'d' $
#删除倒数第N行
sed $(($(cat $|wc -l)-$+1))'d' $
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

4:如何将文本倒置

#4

帖子 oneleaf » 2005-07-30 9:44

将文本倒置,除了tac,还有其它办法,用vim,用awk,都可以实现

1.
line=$(awk 'END{print NR}' filename)
while((line!=0));do awk 'NR=='"$line"'' file;((line--));done
2.
vim -c "g/^/m 0\|wq" file
3.
awk ' {line[NR] = } END {for(i = NR; i > 0; i--) print line[i]}' filename
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

5:截取字符变量的前8位

#5

帖子 oneleaf » 2005-07-30 9:45

截取字符变量的前8位,有6种方法

1.expr substr "$a" 1 8
2.echo $a|awk '{print substr(,1,8)}'
3.echo $a|cut -c1-8
4.echo $
5.expr $a : '\(.\\).*'
6.echo $a|dd bs=1 count=8 2>/dev/null
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

6:删除某目录下除某文件的所有文件

#6

帖子 oneleaf » 2005-07-30 9:45

分删除单个文件和删除多个文件两种情况

1.单个文件的情况下
ls !(filename)|xargs rm

2.多个文件的情况下
ls !(filename1|filename2|...|filenamen)|xargs rm
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

8:列出目录下文件及完整路径

#7

帖子 oneleaf » 2005-07-30 9:45

目前收集了三种方法,比如
1.ls|awk -v a=$(pwd) '{print a"/"}'
2.alias LS='find '

1.ls|awk -v a=$(pwd) '{print a"/"}'
2.alias LS='find '
3.
#!/bin/sh
while [$# -ne 0]
do cd
for file in 'ls'
do echo `pwd`/$file >>$HOME/lsout 2>/dev/null
done
shift
done
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

9:如何取文本每行首字符

#8

帖子 oneleaf » 2005-07-30 9:46

方法太多啦!

1.sed 's/^\(.\).*$/' yourfile
2.cut -b1
3.gawk -F "" '{print }'
4.awk '{print substr(,1,1)}'
5.colrm 2 <filename
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

10:在SED中使用变量

#9

帖子 oneleaf » 2005-07-30 9:46

举例说明:变量a和b,使用sed的替换命令将$a替换为$b
本文包含四种方法,考验大家对meta的理解程度。如果觉得不过关,请复习一下netman老哥的十三问吧。
http://bbs.chinaunix.net/forum/viewtopi ... 8af92d563b

1.eval sed 's/$a/$b/' filename
2.sed "s/$a/$b/" filename
3.sed 's/'$a'/'$b'/' filename
4.sed s/$a/$b/ filename
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

11:取字符串或变量值的最后两位

#10

帖子 oneleaf » 2005-07-30 9:46

7种方法,用到的工具有:awk,sed,rev,cut,grep,colrm,expr,是学习这些工具的很好例子。

1.echo string|awk '{print substr(,length()-1,length())}'
2.echo string|sed 's/\(.*\)\(..$\)//'
3.echo string|rev|cut -c-2|rev
4.echo $-2)):2}或echo $
5.echo string|grep -o ..$
6.echo string|rev|colrm 3|rev
7.expr string : ".*\(..\)$"
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

12:隔行打印或隔行删除

#11

帖子 oneleaf » 2005-07-30 9:47

sed和awk都可以轻松做到

sed版:
sed '1~2' file #删除奇数行,与sed '1~2P' file效果相同
sed '1~2!d' file #删除偶数行

awk版:
awk 'NR%2==0' filename #删除奇数行
awk 'NR%2==1' filename #删除偶数行
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

13:把两行或多行的内容显示在一行中

#12

帖子 oneleaf » 2005-07-30 9:47

还是awk和sed两个老伙计

只有2行的情况:sed 'N;s/\n/\t/g' file
只有3行的情况:sed 'N;N;s/\n/\t/g' file
xargs -n2 <file(不适用于每行多列的情况)

如果有n行,每行不只一列:
awk '{if(NR%2==0)print ;else printf "\t"}' file #2行并为1行
awk '{if(NR%3==0)print ;else printf "\t"}' file #3行并为1行
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

13:一个awk处理文件的例子

#13

帖子 oneleaf » 2005-07-30 9:47

声明:俺只是收集和整理shell版中的问题解决方案,以便学习之用,学习并非原创。在此要感谢shell版的大虾小虾们!也许有一天,可以出个《shell精彩问答集》,来方便更多的人学习shell,使用shell。

1.原始文件
CS 100432= 8.0, 7.4, 6.9, 8.0, 5.0, 4.9, 7.4, 8.0, 9.2,
CS 100441= 8.0, 7.9, 7.8, 7.9, 7.7, 6.6, 4.1, 9.0, 8.4,
CS 100450= 9.0, 9.5, 9.4, 8.2, 8.1, 4.5, 9.3, 8.1, 3.7,
CS 100459= 4.2, 4.9, 7.9, 7.9, 9.1, 8.5, 7.9, 6.1, 7.9,
CS 100468= 7.9, 7.9, 7.9, 4.8, 8.5, 9.1, 9.1, 9.1, 9.8,
CS 100477= 9.8, 9.1, 9.3, 10.6, 9.3, 8.0, 8.0, 9.3, 9.3,
CS 100486= 9.4, 8.2, 8.2, 8.2, 5.7, 6.6, 8.5, 7.6, 8.4,
CS 100495= 4.6, 6.5, 8.4, 6.5, 6.6, 6.6, 6.0, 3.6, 1.1,
CS 100504= 8.6, 7.4, 7.4, 6.9, 8.0, 7.5, 8.6, 9.2, 8.5,
CS 100513= 9.1, 8.5, 8.5, 7.9, 7.8, 7.9, 7.7, 9.0, 11.5,
CS 100522= 10.9, 11.3, 8.1, 8.1, 8.2, 8.1, 9.4, 8.0, 6.3,
CS 100531= 3.7, 6.8, 9.2, 9.8, 8.5, 7.9, 7.9, 7.9, 7.9,
CS 100540= 7.9, 7.9, 7.9, 4.8, 7.9, 8.5, 7.9, 9.1, 7.9,
CS 100549= 9.1, 9.3, 8.7, 9.3, 10.0, 6.2, 8.7, 6.3, 8.0,
CS 100558= 6.4, 8.2, 5.7, 8.2, 8.2, 8.3, 4.5, 4.4, 6.5,
CS 100567= 2.6, 2.0, 6.5, 5.3, 5.3, 6.6, 5.4, 5.5, 3.6,
CS 100576= 5.0, 6.9, 8.6, 8.0, 8.1, 8.0, 4.9, 3.7, 9.2,
CS 100585= 9.7, 9.7, 7.8, 7.2, 11.5, 9.6, 7.9, 7.7, 9.5,
CS 100594= 8.9, 11.4, 6.5, 7.7, 9.4, 10.0, 10.0, 4.5, 8.0,
CS 100603= 4.9, 5.4, 5.4, 7.9, 7.9, 7.9, 6.1, 7.9, 7.9,
CS 100612= 7.9, 7.3, 7.8, 7.3, 6.0, 7.9, 8.6, 9.1, 9.1,
CS 100621= 9.1, 9.4, 9.4, 9.3, 8.1, 4.9, 4.3, 7.4, 8.8,
CS 100630= 9.3, 10.2, 8.3, 4.5, 6.4, 8.2, 5.2, 6.4, 4.4,
CS 100639= 6.5, 4.0, 7.1, 6.5, 9.2, 6.6, 8.5, 6.0, 3.6,
CS 100648= 6.8, 8.0, 5.0, 8.0, 6.9, 7.4, 8.0, 5.6, 4.8,
CS 100657= 8.5, 8.6, 6.6, 6.6, 8.5, 9.0, 7.7, 7.7, 9.5,
CS 100666= 4.6, 9.5, 8.9, 9.5, 9.4, 3.3, 7.5, 8.1, 8.0,
CS 100675= 7.4, 6.8, 7.4, 3.6, 7.9, 7.9, 6.1, 5.4, 7.9,
CS 100684= 9.2, 9.1, 7.9, 7.4, 7.3, 8.5, 8.6, 7.9, 9.2,
CS 100693= 8.8, 9.4, 9.2, 7.6, 8.1, 6.2, 6.3, 10.1, 10.0,
CS 100702= 7.5, 5.6, 9.5, 7.6, 9.4, 4.4, 9.0, 10.1, 8.2,
CS 100711= 9.4, 7.6, 4.0, 9.0, 8.4, 5.9, 6.6, 5.5, 4.3,
CS 100720= 5.1, 8.3, 5.5, 7.5, 7.2, 7.9, 8.1, 8.5, 3.5,
CS 100729= 5.1, 7.8, 5.1, 7.8, 8.4, 8.0, 8.7, 7.6, 9.5,
CS 100738= 8.2, 8.3, 5.1, 9.1, 0.7, 1.7, 8.4, 8.0, 8.0,
CS 100747= 8.4, 8.6, 7.9, 7.1, 7.3, 7.0, 5.5, 7.0, 7.8,
CS 100756= 9.1, 9.2, 9.0, 7.2, 7.6, 8.5, 9.2, 10.0, 8.9,
CS 100765= 8.3, 7.6, 7.6, 5.0, 1.1, 5.6, 10.1, 8.4, 7.9,
CS 100774= 5.0, 7.8, 8.8, 9.1, 6.6, 8.4, 6.4, 7.9, 6.7,
CS 100783= 11.9, 9.0, 4.1, 8.4, 8.8, 7.7, 8.4, 8.4, 6.3,
CS 100792= 7.4, 6.4, 6.8, 6.8, 8.0, 8.0, 8.8, 8.8, 4.4,
CS 100801= 5.4, 5.4, 6.6, 8.1, 9.7, 7.3, 8.0, 8.2, 8.2,
CS 100810= 7.3, 1.2, 0.9, 7.6, 7.1, 8.1, 8.7, 7.0, 8.0,
CS 100819= 7.4, 7.4, 8.0, 8.3, 8.5, 6.1, 7.0, 7.0, 7.8,
CS 100828= 9.1, 10.2, 9.0, 7.7, 7.7, 8.6, 8.6, 7.7, 7.9,
CS 100837= 8.5, 8.3, 8.3, 9.2, 10.2, 9.2, 8.2, 7.6, 5.5,
CS 100846= 8.3, 9.3, 8.8, 7.2, 9.2, 2.8, 7.0, 3.3, 7.7,
CS 100855= 6.4, 6.5, 3.6, 10.5, 5.9, 6.1, 6.1, 8.4,
CS 100863= 6.0,

解决方案:
1.awk '{gsub(/=/,"");n2=;print "\t"n2"=";for(i=4;i<=NF;i++) {n2+=1;print "\t"n2"="$i}}' cc.txt
2.
awk -F= '
{
split(, x, " ");
split(, y, ",");
for(i in y)
{
printf("%s %s = %4.1f\n", x[1], x[2], y[i]);
x[2] = x[2]+1;
}
}' file
3.
nawk 'BEGIN { FS = "," }{
gsub(/CS/,",")
gsub(/\=/,",")
{ for(i = 3; i < NF; i++)
printf("CS %s=%s,\n", ++, $i) }
}' filename

在unix5.0.5下通过
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

14:在插入到匹配字符串后面或者所在的行后面

#14

帖子 oneleaf » 2005-07-30 9:48

用到sed和awk,很简单。

插入字符串A到匹配字符串的后面
1.sed 's/pattern/&A/' filename
2.awk '{print >newfile}' filename

插入到字符串所在的行后面
1.sed '/pattern/a\A' filename
2.awk '/\<pattern\>/{print >"newfile"}' filename
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
头像
oneleaf
论坛管理员
帖子: 10208
注册时间: 2005-03-27 0:06
系统: Ubuntu 12.04
送出感谢: 7 次
接收感谢: 99 次

15:如何按域(field)来消除重复行

#15

帖子 oneleaf » 2005-07-30 9:48

去除某个Field有重复的行

例如:$cat filename
robot 3 xxx 10 @@
amyru 4 xxx 30 (&
cindy 3 zzz 50 %%
blue 9 yyy 30 ##

如果按域来取出唯一性的行,应该用什么

结果比如是这样,按第三个域来取就是

amyru 4 xxx 30 (&
cindy 3 zzz 50 %%
blue 9 yyy 30 ##

按第四个域来取就是
robot 3 xxx 10 @@
amyru 4 xxx 30 (&
cindy 3 zzz 50 %%

答案:
1.sort -k3,3 txt6|awk '}'
2.uniq -f2 -W1 file
注。linux的uniq工具没有W。uniq -f是跳过多少个域进行比较,-s是跳过多少个字符,-W是最多对多少个域进行比较,-w是最多对多少个字符进行比较
3.sort -u +2 -3 就是第2个域以后 第3个域结尾的域
当净其意如虚空,远离妄想及诸取,令心所向皆无碍
回复

回到 “Shell脚本”