shell 中遍历文件的效果比较

本文探讨了在Linux环境下,使用Shell脚本处理特定格式数据文件的方法,并对比了awk、forIn+cat、exec、while循环在遍历文件过程中的效率。重点介绍了awk在流式处理文件方面的优势及其实现的简洁性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设我们有一个数据文件形如下:

A,B

A,C

A,D

B,E

B,F

D,A

D,B

E,G

....

 

需求是要将其转变为如下形式:

A:B,C,D

B:E,F

D:A,B

E,G

......

 

 

需求很简单,循环遍历文件,然后trace第一列即可。

在这里,我们讨论用Shell脚本如何实现这个简单的需求。

 

 

在shell中面对这样的需求,最好的办法莫过于使用awk了,不过除了awk之外,linux也有其他命令能遍历文件内容,比如说cat以及输入重定向等,下面我们就对这几种文件遍历方法做下比较。

 

首先申明一点,关于文件遍历过程中,如果得到目标结果的逻辑是一样的,说白了就是每读入一行,检查第一列而已。

 

1. awk方法:

 

BEGIN{
    FS=","
    curmember="";
}
{
    if(curmember==""){
        curmember=$1;
        offer=$2;
    }
    else if(curmember != $1){
        print curmember":"offer
        curmember=$1;
        offer=$2;
    }
    else{
        offer=offer","$2;
    }
}
END{
    print curmember":"offer;
}

 

 

2. forIn+cat方法:

 

#!/bin/bash
curmember="";
offer="";
#cat orderinfo | while read line
for line in `cat orderinfo`
do
    tmpmember=${line%%,*};
    if [  "$curmember" == ""  ]; then
        curmember=$tmpmember
        offer=${line##*,}
    elif [ "$tmpmember" != "$curmember" ]; then
        echo ${curmember}:${offer}
        curmember=${tmpmember}
        offer=${line##*,}
    else
        offer=${offer},${line##*,}
    fi
done
echo ${curmember}:${offer}

 

 

3. 文件描述符打开文件

 

#!/bin/bash
curmember="";
offer="";
exec 4<orderinfo
while read line<&4
do
    tmpmember=${line%%,*};
    if [  "$curmember" == ""  ]; then
        curmember=$tmpmember
        offer=${line##*,}
    elif [ "$tmpmember" != "$curmember" ]; then
        echo ${curmember}:${offer}
        curmember=${tmpmember}
        offer=${line##*,}
    else
        offer=${offer},${line##*,}
    fi
done
exec 4<&-
echo ${curmember}:${offer}

 

 

4. while循环中直接输入重定向

 

#!/bin/bash
curmember="";
offer="";
while read line
do
    tmpmember=${line%%,*};
    if [  "$curmember" == ""  ]; then
        curmember=$tmpmember
        offer=${line##*,}
    elif [ "$tmpmember" != "$curmember" ]; then
        echo ${curmember}:${offer}
        curmember=${tmpmember}
        offer=${line##*,}
    else
        offer=${offer},${line##*,}
    fi
done<orderinfo
echo ${curmember}:${offer}

 

 

四种方法的执行效率如下,文件行数69000+

 

 

awk   : 185 ms

forIn : 7187 ms

exec  : 7931 ms

while : 7708 ms

 

上述结果中awk速度是最快的,其他三个虽然各有快慢,但都差不多,而且都比awk要慢很多。

 

这也印证了awk在流式处理文件中的先天优势,同时其代码也是最简单的,屏蔽了文件操作的相关内容。

### 批量查找并替换指定字符串的方法 在多个文件中批量查找并替换指定字符串是一项常见的需求,可以通过多种工具和技术实现。以下是几种常见方法及其具体操作方式: #### 方法一:使用 Linux 命令行工具 `find` 和 `perl` 通过组合 `find` 和 `perl` 可以高效地完成此任务。以下是一个具体的命令示例[^1]: ```bash find /path/to/directory -type f -name '要查找的文件名' | xargs perl -pi -e 's|被替换的字符串|替换后的字符串|g' ``` - `/path/to/directory`: 替换为目标目录路径。 - `'要查找的文件名'`: 替换为实际的目标文件模式(如 `.txt`, `*.*` 等)。 - `'被替换的字符串'`: 需要被替换的具体字符串。 - `'替换后的字符串'`: 新的字符串。 这种方法适用于大多数基于 Unix 的操作系统,并能快速处理大量文件。 --- #### 方法二:编写 C 或 MFC 小程序 如果更倾向于编程的方式,则可以开发一个小应用程序来执行该功能[^2]。下面是一段简单的伪代码框架用于说明逻辑流程: ```c #include <stdio.h> #include <string.h> void replaceStringInFile(const char *filename, const char *searchStr, const char *replaceStr) { FILE *fptr; char ch[100]; // 打开原始文件读取数据到缓冲区 fptr = fopen(filename, "r+"); while (fgets(ch, sizeof(ch), fptr)) { if(strstr(ch, searchStr)){ // 替换逻辑... } } } int main() { // 调用函数遍历目标文件夹下的所有文件 } ``` 需要注意的是,C 语言本身并不提供现成的库支持直接修改磁盘上的文本内容,因此需要额外设计算法或者调用第三方库辅助完成整个过程。 --- #### 方法三:利用 Shell 中高级变量替代机制 `${}` 对于某些特殊场景下可能需要用到更加灵活可控的办法时,可考虑采用 shell 自带的一些特性比如参数扩展语法`${parameter:+word}` 来设置条件判断语句[^3]: ```bash for file in $(grep -rlZ old_string .); do sed -i '' s/old_string/new_string/g "$file"; done ``` 上述脚本会先定位含有特定关键词的所有文档列表再逐一实施编辑动作;其中 `-z` 参数允许 NUL 字符作为分隔符从而避免因空白字符引发解析错误的情况发生. 另外一种变体形式如下所示[^4]: ```bash [root@localhost ~]$ grep -rl "target_str" dir_path/* | xargs sed -i 's/target_str/replacement_str/' ``` 以上两种方案各有优劣之处,在选用之前应当充分评估项目环境特点后再做决定。 --- ### 总结 综上所述,无论是借助强大的 GNU 工具链还是亲手打造专属解决方案都可以很好地满足日常工作中关于多文件内字符串检索与更新的需求。选择合适的技术栈取决于个人偏好以及现有资源状况等因素影响最终效果表现差异不大但效率方面可能会存在显著区别所以建议根据实际情况权衡利弊之后择优录取最为理想的做法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值