Bash 逐行读取文件并使用 awk

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21142343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 09:15:59  来源:igfitidea点击:

Bash read file line by line and use awk

bashawk

提问by Alex

I have a sample.txt file in Username:Firstname:Lastname:Telephone numberformat (with several lines, and I want to create a script that converts every line into this format:

我有一个username:Firstname:Lastname:Telephone number格式的 sample.txt 文件(有几行,我想创建一个脚本,将每一行转换成这种格式:

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

So far I've managed to create the citire function that reads and prints OK only if the sample.txt has one line.

到目前为止,我已经设法创建了 citire 函数,该函数仅当 sample.txt 有一行时才能读取和打印 OK。

citire () {
uid=
l=
while read -r line
do
 name=$line
  if [ -z "" ]
  then
  echo -e "$uid:`echo $name|awk -F  ":" '{print $"'$l'"}'`"
  else
  l2=
  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

Can you please tell me what should I modify to make it print each record (line of the file) at a time?

你能告诉我我应该修改什么才能让它一次打印每条记录(文件的行)吗?

Thank you!

谢谢!

回答by Zsolt Botykai

So you basically want something likethis which works without bash:

所以你基本上想要这样的东西,它不需要bash

 gawk 'BEGIN {FS=":"}
       { print "uid:" 
         print " cn:" , 
         print " sn:" 
         print "tel:" 
       }' INPUTFILE

Edit:also see the comments below my answer for proper solutions, credit goes to them!

编辑:另请参阅我的答案下方的评论以获得正确的解决方案,归功于他们!

The shortest solution might be:

最短的解决方案可能是:

awk -F: { printf "uid: %s\n cn: %s %s\n sn: %s\ntel: %s\n", , , , ,  } INPUTFILE

回答by janos

I don't know if you just want to output all records in a fixed format, or if you want the format to be configurable with the citirefunction.

不知道你是只想以固定格式输出所有记录,还是希望格式可以通过citire函数进行配置。

Here's a simple version that outputs in a fixed format, the used in your example:

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

#!/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

And here's a more sophisticated version where citiretakes a "recipe", making the function reusable with different formats:

这是一个更复杂的版本,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

Explanation:

解释:

  • citireinterprets the "recipe" by looping over each item:
    • digit i-- print the field i, 0-based
    • "BR" -- print a line break
    • anything else -- use as a label: print it and a ": " after it
  • Put each line in the array fields, using :as the field separator
  • citire通过遍历每个项目来解释“食谱”:
    • 数字 i-- 打印字段i,从 0 开始
    • "BR" -- 打印换行符
    • 其他任何东西——用作标签:打印它并在它后面加上一个“:”
  • 将每一行放入数组中fields:用作字段分隔符

If you don't like the recipe format, you could probably change the script to make it work like this instead:

如果您不喜欢配方格式,您可能可以更改脚本以使其像这样工作:

citire uid 1 cn 3 2 sn 2 tel 4