C语言 在linux shell开发中实现自定义uniq



我正在开发一个自定义shell。在这个任务中,我需要实现唯一性命令。给定已排序的行,uniq应该能够打印所有唯一值和(如果命令为uniq -c)它们的出现次数。(. 示例代码在最后说明。

我对这个算法没有问题。我写了一个函数,它的运算和我们期望的完全一样。然而,问题是,这些输出和输入类型是什么?我的意思是,当我命令cat input。txt时,这些行是一个字符串还是一个数组?正如我所说,算法是可以的,但我不知道如何在shell中应用正确的算法?任何帮助或想法都是感激的。

$cat input.txt
Cinnamon
Egg
Egg
Flour
Flour
Flour
Milk
Milk
$cat input.txt | uniq
Cinnamon
Egg
Flour
Milk

这些行是一个字符串还是数组

这些行是fork的结果,只是发送给stdout的字符串。

getline在这些情况下非常有用,现在你有了算法,你只需要处理cat的输出。

一个例子:

#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
int main(void)
{
char *str = NULL;
size_t size = 0;
ssize_t len = 0;
int line = 1;
while ((len = getline(&str, &size, stdin)) != -1)
{
printf("%2d) length = %2zd | %s", line++, len, str);
}
free(str);
return 0;
}

gcc -o demo demo.c
cat demo.c | ./demo

输出:

1) length = 32 | #define _POSIX_C_SOURCE 200809L
2) length =  1 | 
3) length = 19 | #include <stdio.h>
4) length = 20 | #include <stdlib.h>
5) length = 23 | #include <sys/types.h>
6) length =  1 | 
7) length = 15 | int main(void)
8) length =  2 | {
9) length = 22 |     char *str = NULL;
10) length = 21 |     size_t size = 0;
11) length = 21 |     ssize_t len = 0;
12) length = 18 |     int line = 1;
13) length =  1 | 
14) length = 54 |     while ((len = getline(&str, &size, stdin)) != -1)
15) length =  6 |     {
16) length = 61 |         printf("%2d) length = %2zd | %s", line++, len, str);
17) length =  6 |     }
18) length = 15 |     free(str);
19) length = 14 |     return 0;
20) length =  2 | }
21) length =  1 | 

格式为字节序列。如何储存取决于你自己。你的设计选择。

cat input.txt打开文件input.txt,读取字节并将其发送到"屏幕";(标准输出)。

uniq从"键盘"(标准输入)和……做独特的事情。并将输出发送到"屏幕"。如果您愿意,您可以自己尝试一下——只运行uniq本身,或uniq -c——停止命令并使其处理最后一行,按enter键完成该行,然后按Ctrl-D。

当你执行cat input.txt | uniq时,shell运行cat input.txt,它运行uniq,但它重定向cat的"屏幕";到uniq的"键盘"。就像你运行cat input.txt然后不管它显示什么,你把它输入uniq

据我所知,你是在写一篇"假装"的文章。Shell,而您的Shell不会实际运行这两个命令并将它们连接起来,因此您对如何做到这一点不感兴趣,只对如何模拟它感兴趣。

需要注意的是,字节直接从catuniq。它不会首先将它们全部保存到一个流中。因此,如果第一个命令很慢,uniq将能够在行准备好后立即处理它们,并且它不必等到第一个命令完成后才开始执行惟一的操作。使用cat命令时,您无法分辨出差异,除非文件非常大,无法用字符串表示,但是使用其他命令时您可能会注意到这一点。

对于您的虚拟shell,按顺序一次处理一行命令可能是最简单的。

当我命令cat input.txt时,这些行只是一个字符串还是它们在数组中给出?

如果您正在执行外部cat命令*,则输出将写入该命令的标准输出。这是I/O,而不是共享内存。一旦这些数据从cat中出现,就不再适合根据cat为它们使用的任何内部数据结构来描述它们。它们只是一串字符。如果另一个命令使用这些数据,那么它会选择自己的数据结构来处理它们。

以及如何您的uniq使用这些数据?两种方式之一:

  1. cat的输出将被重定向到一个文件,uniq随后打开并读取该文件。

    cat input.txt > temp; uniq temp
    

  2. cat的输出将被重定向到uniq的标准输入。

    cat input.txt | uniq
    

UNIX的组织原则之一是,每个I/O端点在逻辑上都是一个文件,因此可以或多或少地以相同的方式处理。在情况(1)中,您将open()fopen()命名文件,而在情况(2)中,您将使用预连接的文件描述符0或stdin流,但是一旦您决定使用哪一个,两者都是一样的。


*如果你正在执行自己的内部cat,那么你比我们更了解细节。

最新更新