2014-01-15 68 views
1

我在中有一个sample.txt文件用户名:名:姓:电话号码格式(带有几行,并且我想创建一个将每行转换为这种格式的脚本:Bash逐行读取文件并使用awk

uid: Username 
cn: LastnameFirstname 
sn: Firstname 
tel:Telephone number 

到目前为止,我已经成功地创建了citire功能读取并打印OK仅在sample.txt的有一行

citire() { 
uid=$1 
l=$2 
while read -r line 
do 
name=$line 
    if [ -z "$3" ] 
    then 
    echo -e "$uid:`echo $name|awk -F ":" '{print $"'$l'"}'`" 
    else 
    l2=$3 
    echo -e "$uid: `echo $name|awk -F ":" '{print $"'$l'" $"'$l2'"}'`" 
fi 
done < /home/alexandrumohora/teste/sample.txt 
} 

citire uid 1 
citire cn 3 2 
citire sn 2 
citire tel 4 

能否请你告诉我我应该怎么修改。使它每次打印每条记录(文件的行)?

谢谢!

+1

外壳是从中调用工具的环境。 awk是解析/处理文本文件的工具。您应该在awk中完成此操作,并从shell中调用它。 –

+1

哦,永远不要像awk和shell那样跳出来,就像''{print $'''$ l'“}''一样。这是完全没有必要的,并且极易出错。 –

回答

5

所以你基本上要这里面没有bash工作:

gawk 'BEGIN {FS=":"} 
     { print "uid:" $1 
     print " cn:" $3, $2 
     print " sn:" $2 
     print "tel:" $4 
     }' INPUTFILE 

编辑:也看到我的回答如下的评论进行适当的解决方案,归功于他们!

最短的解决方案可能是:

awk -F: { printf "uid: %s\n cn: %s %s\n sn: %s\ntel: %s\n", $1, $3, $2, $3, $4 } INPUTFILE 
+3

+1,因为你在正确的轨道上,但你的字段数字错误,“cn”需要连接$ 3 $ 2,“sn”是$ 2。它不需要是gawk,任何awk都可以做,而且你不需要对空间进行硬编码,默认的OFS足够好,并且cn和sn行中不应该有前导空格。例如'print'cn:“,$ 3 $ 2'或者甚至在BEGIN中设置'OFS =':''然后'print”cn“,$ 3 $ 2' –

+3

你也可以用'awk's'printf'来简化它:'awk -F:{printf“uid:%s \ n cn:%s%s \ n sn:%s \ ntel:%s \ n”,$ 1,$ 3,$ 2,$ 3,$ 4} INPUTFILE' – twalberg

+2

@EdMorton && twalberg :谢谢你教我! –

1

我不知道,如果你只是想输出的所有记录在一个固定的格式,或者如果你想要的格式必须与citire功能配置。

下面是一个简单的版本,在一个固定的格式输出,在您的示例中使用:

#!/bin/bash 
data=/home/alexandrumohora/teste/sample.txt 
citire() { 
    while IFS=: read uid sn ln tel; do 
     echo uid: $uid 
     echo cn: $ln$sn 
     echo sn: $sn 
     echo tel:$tel 
    done < "$data" 
} 
citire 

这里还有一个更复杂的版本,其中citire需要一个“处方”,使功能可重复使用的不同格式:

#!/bin/bash 
data=/home/alexandrumohora/teste/sample.txt 
citire() { 
    while IFS=: read -a fields; do 
     for i; do 
      case $i in 
       [0-9]) printf %s "${fields[$i]}" ;; 
       BR) echo ;; 
       *) printf '%s: ' "$i" ;; 
      esac 
     done 
    done < "$data" 
} 
citire uid 0 BR cn 2 1 BR sn 1 BR tel 3 BR 

说明:

  • citire通过遍历每个项目的解释“秘方”:
    • 数字我 - 打印领域,0为主
    • “BR” - 打印一个换行符
    • 别的 - - 使用作为标签:打印和一个“:”之后它
  • 把阵列fields中的每一行,使用:作为字段分隔符

如果你不喜欢的菜谱格式,你很可能修改脚本,使其工作就像这个:

citire uid 1 cn 3 2 sn 2 tel 4 
+0

OP为什么要这样做,而不是简单而强大的awk解决方案?顺便说一下,如果输入文件最终包含任何printf格式化字符,例如它将会失败。一个牌子。 –

+0

@EdMorton好的,我添加了一个强大的bash解决方案,它相当于Zsolt的awk解决方案。我以为OP需要一个可重用的函数,它需要一个配方来控制格式,因此我的原始解决方案,但它看起来像我错了,因为他接受了固定格式的awk解决方案。 – janos

+0

还有一个问题。 printf的概要是'printf格式数据',所以你绝对不应该在用户/文件输入数据的时候写'printf数据',因为数据中的任何格式化字符都会被这样处理,因为你把数据放在格式字符串是应该是奇怪的结果。 'printf'%s'data'是解决这个问题的正确方法,但是在一天结束时,这不是一个有用的应用程序来尝试在bash中工作 - 这正是awk创建的目的。 –