├── .gitignore ├── README.md ├── assets └── preview.png └── src ├── cat ├── Makefile ├── TEST-SUITE │ ├── TEST-FILE_001 │ ├── TEST-FILE_002 │ ├── TEST-FILE_003 │ └── TEST-FILE_004 ├── TEST.py ├── s21_cat.c └── s21_cat.h └── grep ├── Makefile ├── TEST-SUITE ├── TEST-FILE_001 ├── TEST-FILE_002 ├── TEST-FILE_003 ├── TEST-FILE_004 ├── TEST-FILE_005 ├── TEST-FILE_006 └── TEST-TEMPLATE ├── TEST.py ├── s21_grep.c └── s21_grep.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 21-simple-bash-utils 2 | 3 |
PREVIEW_WILL_BE_ADDED_LATER.png
4 | 5 | --- 6 | 7 | Educational project SimpleBashUtils from organization «School 21». 8 | 9 | Development of Bash text utilities cat & grep in C programming languages. Developed functions have all the original flags supported, including paired combinations. 10 | 11 | USEFUL NOTES: 12 | 13 | - there is a significant difference in work of commands on other operating systems. It was not possible to find best testing option, except for using machines on campus. 14 | - cat command has the ability to output contents of several files with one command, however, to submit the s21_cat project, it is enough to be able to process one file. There is a small difference in output, which is better to take into account at start, so as not to create crutches later. 15 | 16 |
17 | [ SPOILER ] Overview of implemented code 18 | 19 | ### s21_cat 20 | 21 | TEMPLATE: `cat [OPTION] [FILE]` 22 | 23 | | No. | Option | Description | Status | 24 | | --- | ----------------------------------------------------------- | -------------------------------------------- | ------ | 25 | | 1 | -b (GNU: --number-nonblank) | numbers only non-empty lines | ✅ | 26 | | 2 | -e подразумевает -v (только GNU: -E то же самое, но без -v) | but also display end-of-line characters as $ | ✅ | 27 | | 3 | -n (GNU: --number) | number all output lines | ✅ | 28 | | 4 | -s (GNU: --squeeze-blank) | squeeze multiple adjacent blank lines | ✅ | 29 | | 5 | -t подразумевает -v (GNU: -T то же самое, но без -v) | but also display tabs as ^I | ✅ | 30 | 31 | ### s21_grep 32 | 33 | TEMPLATE: `grep [OPTION] [TEMPLATE] [FILE]` 34 | 35 | | No. | Option | Description | Status | 36 | | --- | ------- | ------------------------------------------------------------- | ------ | 37 | | 1 | -e | pattern | ✅ | 38 | | 2 | -i | ignore uppercase vs. lowercase | ✅ | 39 | | 3 | -v | invert match | ✅ | 40 | | 4 | -c | output count of matching lines only. | ✅ | 41 | | 5 | -l | output matching files only | ✅ | 42 | | 6 | -n | precede each matching line with a line number | ✅ | 43 | | 7 | -h | output matching lines without preceding them by file names | ✅ | 44 | | 8 | -s | suppress error messages about nonexistent or unreadable files | ✅ | 45 | | 9 | -f file | take regexes from a file | ✅ | 46 | | 10 | -o | output the matched parts of a matching line | ✅ | 47 | 48 |
49 | 50 | — Thanks to 21-SCHOOL for provided assignment and special learning conditions ✌️🔥 51 | 52 | ## Usage 53 | 54 | 1. Clone this repository via 55 | - SSH `git@github.com:rynortheast/21-simple-bash-utils.git` or 56 | - HTTPS `https://github.com/rynortheast/21-simple-bash-utils.git` 57 | 2. Change code base if necessary 58 | 3. Working with s21_cat: 59 | - Run `make s21_cat` to build programm 60 | - Run `make test` to run main tests 61 | 4. Working with s21_grep: 62 | - Run `make s21_grep` to build programm 63 | - Run `make test` to run main tests 64 | -------------------------------------------------------------------------------- /assets/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rynortheast/21-simple-bash-utils/c6ad898e675f57874e0788edd7a2538370dcc9f9/assets/preview.png -------------------------------------------------------------------------------- /src/cat/Makefile: -------------------------------------------------------------------------------- 1 | 2 | FLAGS = -Wall -Wextra -Werror -std=c11 -pedantic 3 | 4 | all: s21_cat 5 | 6 | s21_cat: Makefile s21_cat.h s21_cat.c 7 | gcc $(FLAGS) s21_cat.c -o s21_cat 8 | 9 | test: s21_cat 10 | python3 ./TEST.py 11 | 12 | check: 13 | clang-format -style=Google -n *.c 14 | 15 | rebuild: 16 | make clean 17 | make all 18 | 19 | clean: 20 | rm -f s21_cat 21 | -------------------------------------------------------------------------------- /src/cat/TEST-SUITE/TEST-FILE_001: -------------------------------------------------------------------------------- 1 | fas dfasd 2 | fas df sad 3 | fs 4 | 5 | 6 | krebs 7 | 8 | kepa krepea 9 | 10 | 11 | 12 | a edf 13 | fas dfasd 14 | fas df sad 15 | fs df 16 | 17 | fas dfasd 18 | fas df sad 19 | fs dffas dfasd 20 | fas df sad 21 | fs df 22 | 23 | Q 24 | 2314 23 25 | 4 26 | 27 | 2 28 | 29 | 30 | 31 | d 32 | -------------------------------------------------------------------------------- /src/cat/TEST-SUITE/TEST-FILE_002: -------------------------------------------------------------------------------- 1 | asdf 2 | asdf 3 | 4 | 5 | 6 | 7 | SQUEEZE 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | LAST -------------------------------------------------------------------------------- /src/cat/TEST-SUITE/TEST-FILE_003: -------------------------------------------------------------------------------- 1 | aboba_one 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | floppa_two 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | shleppa_three 25 | 26 | 27 | 28 | 29 | 30 | kopa_four -------------------------------------------------------------------------------- /src/cat/TEST-SUITE/TEST-FILE_004: -------------------------------------------------------------------------------- 1 | aboba_one$ 2 | $ 3 | floppa_two$ 4 | $ 5 | shleppa_three$ 6 | $ 7 | kopa_four -------------------------------------------------------------------------------- /src/cat/TEST.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | from itertools import combinations_with_replacement 4 | from random import shuffle 5 | from os import system 6 | 7 | falshivka = "./s21_cat" 8 | original = "cat" 9 | 10 | file_name = 'TEST-FILE' 11 | file_format = ".testing" 12 | 13 | suite = [ 14 | 'TEST-SUITE/TEST-FILE_002' 15 | ] 16 | 17 | flags = { 18 | '-b', 19 | '-e', 20 | '-n', 21 | '-s', 22 | '-v', 23 | '-t' 24 | } 25 | 26 | all_var = list(combinations_with_replacement(flags, len(flags))) 27 | 28 | def file_comparison(a, b): 29 | with open(a) as file_1: 30 | with open(b) as file_2: 31 | a, b = file_1.read(), file_2.read() 32 | if a != b: 33 | 34 | count = 0 35 | for i in range(len(a)): 36 | if a[i] == '\n': 37 | count += 1 38 | if len(b) == i: 39 | break 40 | if a[i] != b[i]: 41 | break 42 | 43 | print("===============A===============") 44 | print(a[max(0, i-50):min(len(a), i+50)]) 45 | print("===============B===============") 46 | print(b[max(0, i-50):min(len(b), i+50)]) 47 | print("===============================") 48 | print("Line:", count, " char:", i) 49 | input("Press any key to continue:\n") 50 | 51 | else: 52 | print("\033[42m\033[1m YES \033[0m") 53 | 54 | 55 | for test in range(len(all_var)): 56 | cur_flags_ = all_var[test] 57 | for cur_flags in (cur_flags_, set(cur_flags_)): 58 | shuffle(suite) 59 | print(f"Current TEST [{test + 1} / {len(all_var)}] - ", end='') 60 | for i, func in (('0', falshivka), ('1', original)): 61 | m_str = f'{func} {" ".join(cur_flags)} {" ".join(suite)} > {file_name+"-"+i+file_format}' 62 | system("echo '{}' >> commands.testing".format(m_str)); 63 | system(m_str) 64 | file_comparison(file_name+'-0'+file_format, 65 | file_name+'-1'+file_format) 66 | 67 | system('rm -rf *' + file_format) 68 | -------------------------------------------------------------------------------- /src/cat/s21_cat.c: -------------------------------------------------------------------------------- 1 | #include "s21_cat.h" 2 | 3 | int main(int argc, char **argv) { 4 | s21_cat_programm(argc, argv); 5 | return 0; 6 | } 7 | 8 | void s21_cat_programm(int argc, char **argv) { 9 | if (argc > 1) { 10 | options config = {0}; 11 | if (scanOptions(argc, argv, &config)) { 12 | for (int x = (argc - config.numberFiles); x < argc; x += 1) { 13 | FILE *file = fopen(argv[x], "r"); 14 | if (file != NULL) 15 | fclose(printData(file, &config)); 16 | else 17 | fprintf(stderr, ERROR_01, argv[x]); 18 | } 19 | } 20 | } 21 | } 22 | 23 | int scanOptions(int argc, char **argv, options *config) { 24 | int indexStartFiles = 1, status = 1, x = 1; 25 | 26 | for (; (x < argc && argv[x][0] == '-'); indexStartFiles = (x += 1)) { 27 | if (!strcmp(argv[x], "-b") || !strcmp(argv[x], "--number-nonblank")) { 28 | config->b = (config->n = 0) + 1; 29 | } else if (!strcmp(argv[x], "-s") || !strcmp(argv[x], "--squeeze-blank")) { 30 | config->s = 1; 31 | } else if (!strcmp(argv[x], "-n") || !strcmp(argv[x], "--number")) { 32 | config->n = config->b ? 0 : 1; 33 | } else if (!strcmp(argv[x], "-T")) { 34 | config->t = 1; 35 | } else if (!strcmp(argv[x], "-v")) { 36 | config->v = 1; 37 | } else if (!strcmp(argv[x], "-t")) { 38 | config->t = 1; 39 | config->v = 1; 40 | } else if (!strcmp(argv[x], "-e")) { 41 | config->e = 1; 42 | config->v = 1; 43 | } else if (!strcmp(argv[x], "-E")) { 44 | config->e = 1; 45 | } else { 46 | fprintf(stderr, ERROR_02, argv[x][1]); 47 | status = 0; 48 | } 49 | } 50 | 51 | config->numberFiles = argc - indexStartFiles; 52 | 53 | return status; 54 | } 55 | 56 | FILE *printData(FILE *file, options *config) { 57 | for (char sym = '0'; (sym = getc(file)) != EOF;) { 58 | config->emptyLine = 0; 59 | if (config->s && config->counterS == 0 && sym == '\n') { 60 | config->counterS += 1; 61 | } else if (config->counterS != 0 && sym == '\n') { 62 | config->counterS += 1; 63 | config->emptyLine = 1; 64 | } else if (config->counterS > 1 && sym != '\n') { 65 | config->counterS = 0; 66 | config->e ? printf("$\n") : printf("\n"); 67 | if (config->n != 0) printf("%6d\t", config->n++); 68 | } else { 69 | config->counterS = 0; 70 | } 71 | if (config->n != 0 || config->b != 0) { 72 | if (config->newLine == 1 && !(config->newLine = 0)) 73 | printf("%6d\t", config->n++); 74 | if (config->n == 1) printf("%6d\t", config->n++); 75 | if (config->b == 1) printf("%6d\t", config->b++); 76 | if (sym == '\n' && config->n != 0 && config->emptyLine == 0) 77 | config->newLine = 1; 78 | if (sym == '\n' && config->b != 0) config->counterB += 1; 79 | if (sym != '\n' && config->counterB != 0 && config->counterS == 0) 80 | if (!(config->counterB = 0)) printf("%6d\t", config->b++); 81 | } 82 | if (sym == '\n' && config->e && config->emptyLine == 0) printf("$"); 83 | if (config->v) { 84 | if (sym < 32 && sym != 9 && sym != 10) 85 | if (sym += 64) printf("^"); 86 | if (sym == 127) 87 | if ((sym = '?')) printf("^"); 88 | } 89 | if (config->t && sym == '\t') 90 | if ((sym = 'I')) printf("^"); 91 | if (config->emptyLine == 0) printf("%c", sym); 92 | } 93 | return file; 94 | } 95 | -------------------------------------------------------------------------------- /src/cat/s21_cat.h: -------------------------------------------------------------------------------- 1 | #ifndef SRC_CAT_S21_CAT_H_ 2 | #define SRC_CAT_S21_CAT_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define ERROR_01 "s21_cat: %s: No such file or directory\n" 9 | #define ERROR_02 "s21_cat: invalid option -- '%c'\n" 10 | 11 | typedef struct { 12 | int b; 13 | int e; 14 | int n; 15 | int s; 16 | int t; 17 | int v; 18 | int newLine; 19 | int counterB; 20 | int counterS; 21 | int emptyLine; 22 | int numberFiles; 23 | } options; 24 | 25 | void s21_cat_programm(int argc, char **argv); 26 | 27 | int scanOptions(int argc, char **argv, options *config); 28 | FILE *printData(FILE *file, options *config); 29 | 30 | #endif // SRC_CAT_S21_CAT_H_ 31 | -------------------------------------------------------------------------------- /src/grep/Makefile: -------------------------------------------------------------------------------- 1 | 2 | FLAGS = -Wall -Wextra -Werror -std=c11 -pedantic 3 | 4 | all: s21_grep 5 | 6 | s21_grep: Makefile s21_grep.h s21_grep.c 7 | gcc $(FLAGS) s21_grep.c -o s21_grep 8 | 9 | test: s21_grep 10 | python3 ./TEST.py 11 | 12 | check: 13 | clang-format -style=Google -n *.c 14 | 15 | rebuild: 16 | make clean 17 | make all 18 | 19 | clean: 20 | rm -f s21_grep 21 | -------------------------------------------------------------------------------- /src/grep/TEST-SUITE/TEST-FILE_001: -------------------------------------------------------------------------------- 1 | 2 | 3 | ryuihn 4 | yudcsbapvndfgyhuijkl;'rtyuiop[]ghjkl;' 5 | 6 |   7 | 8 | 9 | 10 | 234567 11 | int get_flags(int argc, char** argv, flag *flags, char** template) { 12 | int i = 1; 13 | while (argv[i][0] == '-' && argc > i + 1) { 14 | if (!strcmp(argv[i], "-e")) { 15 | if (flags -> e == 0) { // && flags.f == 0) { 16 | (*template) = (char *) malloc(sizeof(char) * (strlen(argv[++i]) + 1)); 17 | if (*template) 18 | strcpy((*template), argv[i]); 19 | } else { 20 | (*template) = (char *) s21_reallocf((*template),ghjkl;kjhgfdsasdfghjkl;'\';lkjhgfdssdfghjkl;'\rtyuiop[]sizeof(char) * (strlen(*template) + 2 + strlen(argv[++i])));if (*template) {strcat((*template), "|"); 21 | strcat((*template), argv[i]); 22 | } 23 | } 24 | flags -> e = 1; 25 | } 26 | } 27 | if (!flags -> e) { 28 | (*template) = (char *) malloc(sizeof(char) * (strlen(argv[i]) + 1)); 29 | if (*template) 30 | strcpy((*template), argv[i++]); 31 | } 32 | return i; 33 | } 34 | -------------------------------------------------------------------------------- /src/grep/TEST-SUITE/TEST-FILE_002: -------------------------------------------------------------------------------- 1 | Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”. 2 | 3 | 4 | Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation 5 | License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, 6 | with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled 7 | “GNU Free Documentation License”. 8 | a 9 | Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Docu 10 | mentation License”. 11 | 12 | 13 | 14 | 15 | aboba_flex -------------------------------------------------------------------------------- /src/grep/TEST-SUITE/TEST-FILE_003: -------------------------------------------------------------------------------- 1 | isadfasdfa 2 | fasdfasdf 3 | 4 | Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”. 5 | _\n 6 | Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation 7 | License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, 8 | with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled 9 | “GNU Free Documentation License”. 10 | a 11 | Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Docu 12 | mentation License”. 13 | 14 | permission 15 | permission permission permission permission 16 | permission permission permission 17 | permission permission 18 | permission 19 | permission 20 | permissionpermission 21 | permissionpermissionpermission 22 | 23 | aboba_flex__________FLEXOLOG 24 | 25 | is 26 | 27 | 28 | 29 | is -------------------------------------------------------------------------------- /src/grep/TEST-SUITE/TEST-FILE_004: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 10 | 10 11 | 12 | 1 13 | 14 | 1 15 | 16 | 2 17 | 18 | 19 | floppa 20 | 21 | 22 | aboba 23 | 24 | 25 | 26 | special 27 | 28 | 29 | 30 | 31 | is 32 | 33 | 34 | 35 | is -------------------------------------------------------------------------------- /src/grep/TEST-SUITE/TEST-FILE_005: -------------------------------------------------------------------------------- 1 | At vero eos et accusamus et iusto odio dignissimos ducimus, quis nostrum exercitationem ullam corporis suscipit laboriosam, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua!At vero eos et accusamus et iusto odio dignissimos ducimus, quisdduis nostrum exercitationem ullam corporis suscipit laboriosam, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua!At vero eos et accusamus et iusto odio dignissimos ducimus, quisdd -------------------------------------------------------------------------------- /src/grep/TEST-SUITE/TEST-FILE_006: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rynortheast/21-simple-bash-utils/c6ad898e675f57874e0788edd7a2538370dcc9f9/src/grep/TEST-SUITE/TEST-FILE_006 -------------------------------------------------------------------------------- /src/grep/TEST-SUITE/TEST-TEMPLATE: -------------------------------------------------------------------------------- 1 | if 2 | [0-9] 3 | -------------------------------------------------------------------------------- /src/grep/TEST.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | from itertools import combinations_with_replacement 4 | from random import shuffle 5 | from os import system 6 | 7 | falshivka = "./s21_grep" 8 | original = "grep" 9 | 10 | file_name = 'TEST-FILE' 11 | file_format = ".testing" 12 | 13 | template = '[0-9]' 14 | test_file = './TEST-SUITE/TEST-FILE_001' 15 | test_template = './TEST-SUITE/TEST-TEMPLATE' 16 | 17 | suite_flag = [ 18 | f'-e {template} -e {test_template} {test_file}', 19 | f'-f {test_template} -e {template} {test_file}', 20 | f'-f {test_template} s21_grep.c s21_grep.h', 21 | f'-vf {test_template} {test_file}', 22 | f'-cf {test_template} {test_file}', 23 | f'-lf {test_template} {test_file}', 24 | f'-nf {test_template} {test_file}', 25 | f'-hf {test_template} {test_file}', 26 | f'-h if {test_file} s21_grep.h', 27 | f'-ie {template} {test_file}', 28 | f'-ve {template} {test_file}', 29 | f'-ce {template} {test_file}', 30 | f'-le {template} {test_file}', 31 | f'-ne {template} {test_file}', 32 | f'-he {template} {test_file}', 33 | f'-se {template} {test_file}', 34 | f'-oe {template} {test_file}', 35 | f'-iv {template} {test_file}', 36 | f'-ic {template} {test_file}', 37 | f'-il {template} {test_file}', 38 | f'-in {template} {test_file}', 39 | f'-ih {template} {test_file}', 40 | f'-is {template} {test_file}', 41 | f'-io {template} {test_file}', 42 | f'-vc {template} {test_file}', 43 | f'-vl {template} {test_file}', 44 | f'-vn {template} {test_file}', 45 | f'-vh {template} {test_file}', 46 | f'-vs {template} {test_file}', 47 | f'-vo {template} {test_file}', 48 | f'-cl {template} {test_file}', 49 | f'-cn {template} {test_file}', 50 | f'-ch {template} {test_file}', 51 | f'-cs {template} {test_file}', 52 | f'-co {template} {test_file}', 53 | f'-ln {template} {test_file}', 54 | f'-lh {template} {test_file}', 55 | f'-ls {template} {test_file}', 56 | f'-lo {template} {test_file}', 57 | f'-nh {template} {test_file}', 58 | f'-ns {template} {test_file}', 59 | f'-no {template} {test_file}', 60 | f'-hs {template} {test_file}', 61 | f'-ho {template} {test_file}', 62 | f'-l {template} {test_file}', 63 | f'-v {template} {test_file}', 64 | f'-c {template} {test_file}', 65 | f'-n {template} {test_file}', 66 | f'-o {template} {test_file}', 67 | f'[0-9] {test_file}', 68 | f'-i RY {test_file}' 69 | ] 70 | 71 | # all_var = list(combinations_with_replacement(suite_flag, len(suite_flag))) 72 | 73 | def file_comparison(a, b): 74 | with open(a) as file_1: 75 | with open(b) as file_2: 76 | a, b = file_1.read(), file_2.read() 77 | if a != b: 78 | 79 | count = 0 80 | for i in range(len(a)): 81 | if a[i] == '\n': 82 | count += 1 83 | if len(b) == i: 84 | break 85 | if a[i] != b[i]: 86 | break 87 | 88 | print("===============A===============") 89 | print(a[max(0, i-50):min(len(a), i+50)]) 90 | print("===============B===============") 91 | print(b[max(0, i-50):min(len(b), i+50)]) 92 | print("===============================") 93 | print("Line:", count, " char:", i) 94 | input("Press any key to continue:\n") 95 | 96 | else: 97 | print("\033[42m\033[1m YES \033[0m") 98 | 99 | for index in range(len(suite_flag)): 100 | print(f'Current TEST [{index + 1} / {len(suite_flag)}] - {suite_flag[index]} - ', end='') 101 | system(f'{falshivka} {suite_flag[index]} > {file_name + "-0" + file_format}') 102 | system(f'{original} {suite_flag[index]} > {file_name + "-1" + file_format}') 103 | file_comparison(file_name+'-0'+file_format, file_name+'-1'+file_format) 104 | 105 | system('rm -rf *' + file_format) 106 | -------------------------------------------------------------------------------- /src/grep/s21_grep.c: -------------------------------------------------------------------------------- 1 | #include "s21_grep.h" 2 | 3 | int main(int argc, char **argv) { 4 | s21_grep_programm(argc, argv); 5 | return 0; 6 | } 7 | 8 | void s21_grep_programm(int argc, char **argv) { 9 | if (argc > 1) { 10 | char *temp = NULL; 11 | options config = {0}; 12 | 13 | for (int x = scanOptions(argc, argv, &config, &temp); x < argc; x += 1) 14 | s21_grep(argv[x], config, temp); 15 | 16 | if (temp != NULL) free(temp); 17 | } 18 | } 19 | 20 | int scanOptions(int argc, char **argv, options *config, char **template) { 21 | for (int sym = 0; (sym = getopt(argc, argv, "e:ivclnhsf:o")) != (-1);) { 22 | switch (sym) { 23 | case 'i': 24 | config->i = 1; 25 | break; 26 | case 'v': 27 | config->v = 1; 28 | break; 29 | case 'c': 30 | config->c = 1; 31 | break; 32 | case 'l': 33 | config->l = 1; 34 | break; 35 | case 'n': 36 | config->n = 1; 37 | break; 38 | case 'h': 39 | config->h = 1; 40 | break; 41 | case 's': 42 | config->s = 1; 43 | break; 44 | case 'o': 45 | config->o = 1; 46 | break; 47 | case 'e': 48 | setConfigE(config, template, optarg); 49 | break; 50 | case 'f': 51 | setConfigF(config, template, optarg); 52 | break; 53 | } 54 | } 55 | if ((config->e || config->f) == 0) { 56 | createTemplate(template, argv[optind]); 57 | optind += 1; 58 | } 59 | setupConfig(config, argc); 60 | return optind; 61 | } 62 | 63 | void s21_grep(char *path, options config, char *template) { 64 | FILE *file = fopen(path, "r"); 65 | if (file != NULL) { 66 | for (char sym = '0'; (sym = getc(file)) != EOF;) { 67 | char *line = calloc(256, 1); 68 | config.numberLine += 1; 69 | int length = 0; 70 | 71 | for (line[length] = '\0'; sym != EOF && sym != '\n'; sym = getc(file)) { 72 | line[length] = sym; 73 | line[length += 1] = '\0'; 74 | if (length % 255 == 0) line = increaseLengthStr(line, length + 256); 75 | } 76 | 77 | printMainData(line, &config, template, path); 78 | free(line); 79 | } 80 | printfAuxData(config, path); 81 | fclose(file); 82 | } else if (config.s == 0) { 83 | fprintf(stderr, ERROR_01, path); 84 | } 85 | } 86 | 87 | void setConfigF(options *config, char **template, char *optarg) { 88 | FILE *file = fopen(optarg, "r"); 89 | if (file != NULL) { 90 | for (char sym = '0'; (sym = getc(file)) != EOF;) { 91 | int length = 0; 92 | char *line = calloc(256, 1); 93 | 94 | for (line[length] = '\0'; sym != EOF && sym != '\n'; sym = getc(file)) { 95 | line[length] = sym; 96 | line[length += 1] = '\0'; 97 | if (length % 255 == 0) 98 | line = (char *)increaseLengthStr(line, length + 256); 99 | } 100 | 101 | if (!(config->e || config->f)) 102 | config->f = createTemplate(template, line); 103 | else 104 | addTemplate(template, line); 105 | free(line); 106 | } 107 | fclose(file); 108 | } else if (config->s == 0) { 109 | fprintf(stderr, ERROR_01, optarg); 110 | } 111 | } 112 | 113 | void setConfigE(options *config, char **template, char *optarg) { 114 | if (!(config->e || config->f)) 115 | config->e = createTemplate(template, optarg); 116 | else 117 | addTemplate(template, optarg); 118 | } 119 | 120 | void printfAuxData(options config, char *path) { 121 | if (config.c) { 122 | if (config.l) { 123 | config.countFiles > 1 ? printf("%s:1\n", path) : printf("1\n"); 124 | } else { 125 | if (config.countFiles > 1) printf("%s:", path); 126 | printf("%i\n", config.countMatches); 127 | } 128 | } 129 | if (config.l && config.countMatches) printf("%s\n", path); 130 | } 131 | 132 | void printMainData(char *line, options *config, char *template, char *path) { 133 | regex_t regex; 134 | if (regcomp(®ex, template, config->i ? REG_ICASE : REG_EXTENDED) == 0) { 135 | if (regexec(®ex, line, 0, NULL, 0) == config->v) { 136 | config->countMatches += 1; 137 | if ((config->c || config->l) == 0) { 138 | if (config->countFiles > 1 && !(config->h)) printf("%s:", path); 139 | if (config->n) printf("%i:", config->numberLine); 140 | if (!config->o) 141 | printf("%s\n", line); 142 | else 143 | printfConfigO(regex, line, *config); 144 | } 145 | } 146 | regfree(®ex); 147 | } 148 | } 149 | 150 | void printfConfigO(regex_t regex, char *line, options config) { 151 | while (regexec(®ex, line, 0, NULL, 0) == config.v) { 152 | char *aux = (char *)calloc(strlen(line) + 1, 1); 153 | strcpy(aux, line); 154 | int end = strlen(line); 155 | while (regexec(®ex, aux, 0, NULL, 0) == config.v) { 156 | end--; 157 | aux[strlen(aux) - 1] = 0; 158 | } 159 | aux[strlen(aux)] = line[strlen(aux)]; 160 | int start = 0; 161 | while (regexec(®ex, aux, 0, NULL, 0) == config.v && strlen(aux) > 0) { 162 | start++; 163 | int j = 0; 164 | while (aux[j] != 0) { 165 | aux[j] = aux[j + 1]; 166 | j++; 167 | } 168 | } 169 | start--; 170 | int i = strlen(aux); 171 | while (i != 0) { 172 | aux[i] = aux[i - 1]; 173 | i--; 174 | } 175 | aux[0] = line[start]; 176 | printf("%s\n", aux); 177 | free(aux); 178 | i = start + 1; 179 | while (line[i] != 0) { 180 | line[i - start - 1] = line[i]; 181 | i++; 182 | } 183 | line[i - start - 1] = 0; 184 | } 185 | } 186 | 187 | void setupConfig(options *config, int argc) { 188 | if (config->o && (config->l || config->v || config->c)) config->o = 0; 189 | config->countFiles = argc - optind; 190 | } 191 | 192 | int createTemplate(char **str, char *optarg) { 193 | *str = calloc(strlen(optarg) + 1, 1); 194 | if (*str) strcpy(*str, optarg); 195 | return str ? 1 : 0; 196 | } 197 | 198 | void addTemplate(char **str, char *optarg) { 199 | *str = increaseLengthStr(*str, strlen(*str) + strlen(optarg) + 2); 200 | if (*str) strcat(strcat(*str, "|"), optarg); 201 | } 202 | 203 | void *increaseLengthStr(void *str, int size) { 204 | char *aux = realloc(str, size); 205 | return aux; 206 | } 207 | -------------------------------------------------------------------------------- /src/grep/s21_grep.h: -------------------------------------------------------------------------------- 1 | #ifndef SRC_GREP_S21_GREP_H_ 2 | #define SRC_GREP_S21_GREP_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define ERROR_01 "s21_grep: %s: No such file or directory\n" 11 | 12 | typedef struct { 13 | int e; 14 | int i; 15 | int v; 16 | int c; 17 | int l; 18 | int n; 19 | int h; 20 | int s; 21 | int f; 22 | int o; 23 | int countFiles; 24 | int numberLine; 25 | int countMatches; 26 | } options; 27 | 28 | void s21_grep_programm(int argc, char **argv); 29 | 30 | int scanOptions(int argc, char **argv, options *config, char **template); 31 | void printMainData(char *str, options *options, char *tmpl, char *name); 32 | void setConfigF(options *config, char **template, char *optarg); 33 | void setConfigE(options *config, char **template, char *optarg); 34 | void printfConfigO(regex_t my_regex, char *str, options config); 35 | void s21_grep(char *name, options config, char *tmpl); 36 | void printfAuxData(options config, char *path); 37 | void *increaseLengthStr(void *str, int size); 38 | int createTemplate(char **str, char *optarg); 39 | void setupConfig(options *config, int argc); 40 | void addTemplate(char **str, char *optarg); 41 | 42 | #endif // SRC_GREP_S21_GREP_H_ 43 | --------------------------------------------------------------------------------