What is wrong in this grep command? - linux

Okay... so I'm trying to make a dictionary using Crunch and Grep I've also tried using Perl instead.
crunch 8 12 1234567890 -d 2# | grep -v '\([0-9]\) .*\1.*\1.*\1.*' | grep 41106041
So, basically i want to filter all passwords which numbers appear 3 times
grep 41106041
Is just to test if the code works.. and it doesn't.
I've also tried some "C style" perl code as I'm still a newbie to perl:
#! /bin/perl
#lines=<STDIN>;
$c=0;
foreach $number(#lines)
{
$acum=undef;
$pos=0;
while($pos <= &countdig($number))
{
if ($acum=$digit)
{
$c=$c+1;
}
else
{
$c=0;
}
$acum=$digit;
}
if ($c=3)
{
print "$number"." ";
}
$c=0;
}
sub countdig
{
my($j)=0;
chomp(my(#n)=#_);
print "first dig $n[$j] \n";
while($_[0][$j]>=0 && $_[0][j]<=9)
{
$j+=1;
}
print "j total : $j \n";
$j;
}
Countdig is supposed to count the number of digits but thing is.. I can't access a scalar variable as a list.. so well if you guys could explain me how to make it work it would be very appreciated.

Your grep is failing because there is a stray space in your pattern, and you are searching for 4 identical digits (the one captured, plus three more by backreference).
$ printf '12345678\n41106041\n87654321\n' | grep -v '\(.\).*\1.*\1'
12345678
87654321
The problem is not being a newbie to Perl, cause it's easy to turn a C solution
// For each line
char *num = ...;
int digits[10];
for (int i=0; i<10; ++i) {
digits[i] = 0;
}
const char *p = num;
int triple = 0;
for (; *p && *p != '\n'; ++p) {
if (++digits[*p - '0'] == 3) {
triple = 1;
break;
}
}
if (triple) {
...
}
into a Perl solution
while (my $num = <>) {
chomp($num);
my #digits;
my $triple;
for my $digit (split //, $num) {
if (++$digits[$digit] == 3) {
$triple = 1;
last;
}
}
say $num if $triple;
}
Of course, a Perl programmer might very well use the same approach you used for grep.
while (<>) {
if (!/(.).*\1.*\1/) {
print;
}
}

echo 41106041 | grep -v '\([0-9]\).*\1.*\1.*

Related

perl remove string block from file and save to file

I have a file that looks like this:
string 1 {
abc { session 1 }
fairPrice {
ID LU0432618274456
Source 4
service xyz
}
}
string 2 {
abc { session 23 }
fairPrice {
ID LU036524565456171
Source 4
service tzu
}
}
My program should read in the file with a search-parameter given (for example "string 1") and search the complete block until "}" and remove that part from the file. Can someone assist on that...I have some code so far but how can I do the removal and saving to the same file again?
my $fh = IO::File->new( "$fname", "r" ) or die ( "ERROR: Strategy file \"$fname\" not found." );
while($line=<$fh>)
{
if ($line =~ /^\s*string 1\s*\w+\s*\{\s*$/) {
$inside_json_msg = 1;
$msg_json .= $line;
}
else {
if ($inside_json_msg)
{
if ($line =~ m/^\}\s*$/) {
$msg_json.= $line if defined($line);
$inside_json_msg = 0;
} else {
$msg_json .= $line;
}
}
}
}
You code mentions JSON, but your data isn't JSON. If it is JSON and you've just transcribed it badly, then please use a JSON library.
But if your data isn't JSON, then something like this will do the trick.
#!/usr/bin/perl
use strict;
use warnings;
my $match = shift or die "I need a string to match\n";
while (<DATA>) {
# If this is the start of a block we want to remove...
if (/^\s*$match\s+{/) {
# Set $braces to 1 (or 0 if the block closes on this line)
my $braces = /}/ ? 0 : 1;
# While $braces is non-zero
while ($braces) {
# Read the next line of the file
$_ = <DATA>;
# Increment or decrement $braces as appropriate
$braces-- if /}/;
$braces++ if /{/;
}
} else {
# Otherwise, just print the line
print;
}
}
__DATA__
string 1 {
abc { session 1 }
fairPrice {
ID LU0432618274456
Source 4
service xyz
}
}
string 2 {
abc { session 23 }
fairPrice {
ID LU036524565456171
Source 4
service tzu
}
}
Currently, this just prints the output to the console. And I use the DATA filehandle for easier testing. Switching to use real filehandles is left as an exercise for the reader :-)
Update: I decided that I didn't like all the incrementing and decrementing of $braces using regex matches. So here's another (improved?) version that uses y/.../.../ to count the occurrences of opening and closing braces in the line. It's possible that this version might be slightly less readable (the syntax highlighter certainly thinks so).
#!/usr/bin/perl
use strict;
use warnings;
my $match = shift or die "I need a string to match\n";
while (<DATA>) {
if (/^\s*$match\s+{/) {
my $braces = y/{// - y/}//;
while ($braces) {
$_ = <DATA>;
$braces -= y/}//;
$braces += y/{//;
}
} else {
print;
}
}
__DATA__
string 1 {
abc { session 1 }
fairPrice {
ID LU0432618274456
Source 4
service xyz
}
}
string 2 {
abc { session 23 }
fairPrice {
ID LU036524565456171
Source 4
service tzu
}
}
Update 2: Ok, I originally said that dealing with real filehandles would be left as an exercise for the reader. But here's a version that does that.
#!/usr/bin/perl
use strict;
use warnings;
my $match = shift or die "I need a string to match\n";
open my $fh, '+<', 'data' or die $!;
# Read all the data from the file
my #data = <$fh>;
# Empty the file
seek $fh, 0, 0;
truncate $fh, 0;
my $x = 0;
while ($x <= $#data) {
$_ = $data[$x++];
if (/^\s*$match\s+{/) {
my $braces = y/{// - y/}//;
while ($braces) {
$_ = $data[$x++];
$braces -= y/}//;
$braces += y/{//;
}
} else {
print $fh $_;
}
}
Currently, I've hard-coded the filename to be data. I hope it's obvious how to fix that.
Can use Text::Balanced to break the text into blocks delimited by {}, in a way that also keeps the text preceding and following the blocks.
In that list drop the element with the specific skip-pattern (string 1 here) and its following block and retain everything else. Then overwrite the source file with that.
use warnings;
use strict;
use Path::Tiny;
use Text::Balanced qw(extract_bracketed extract_multiple);
my $file = shift // die "Usage: $0 file\n"; #/
my $text = path($file)->slurp;
# returns: 'string 1', BLOCK, 'string 2', BLOCK (may have spaces/newlines)
my #elems = extract_multiple(
$text, [ sub { extract_bracketed($text, '{}') } ]
);
my $skip_phrase = 'string 1';
my (#text_keep, $skip);
for (#elems) {
if (/$skip_phrase/) {
$skip = 1;
next;
}
elsif ($skip) {
$skip = 0;
next
}
push #text_keep, $_;
}
print for #text_keep;
# Overwrite source; uncomment when tested
#open my $fh_out, '>', $file or die "Can't open $file: $!";
#print $fh_out $_ for #text_keep;
Tested with files with more text and blocks, both before and after the one to drop.
Another tool that can be used to extract delimited chunks is in Regexp::Common, see this post.
I would use proper json as format and jq as processor for that format. Rewriting a hack in perl does not make much sense.
Here is an example using Regexp::Grammars:
use feature qw(say);
use strict;
use warnings;
use Data::Printer;
use Regexp::Grammars;
{
my ($block_name, $block_num) = #ARGV;
my $parser = qr!
<nocontext:>
<blocks>
<rule: blocks> <[block]>+
<rule: block> <block_name> <block_num> <braced_item>
<token: block_name> \w+
<token: block_num> \d+
<rule: braced_item> \{ (?: <escape> | <braced_item> | [^{}] )* \}
<token: escape> \\ .
!xms;
my $data = read_file('cfg.txt');
if ($data =~ $parser) {
print_blocks( $/{blocks}{block}, $block_name, $block_num );
}
else {
warn "No match";
}
}
sub print_blocks {
my ( $blocks, $block_name, $block_num ) = #_;
for my $block (#$blocks) {
next if ($block->{block_name} eq $block_name)
&& ($block->{block_num} == $block_num);
say $block->{block_name}, " ", $block->{block_num},
" ", $block->{braced_item}{braced_item};
}
}
sub read_file {
my ( $fn ) = #_;
open ( my $fh, '<', $fn ) or die "Could not open file '$fn': $!";
my $str = do { local $/; <$fh> };
close $fh;
return $str;
}

Sharing a thread variable without making it global (Perl)

I'm trying to write a simple script that uses threads and shares a variable, but I don't want to make this variable global to the whole script. Below is a simplified example.
use strict;
use warnings;
use threads;
use threads::shared;
my $val:shared;
# Create threads
for my $i (1 .. 5) {
threads->create(\&do_something, $i);
}
# Wait for all threads to complete
map { $_->join(); } threads->list();
# $val is global to the script so this line will work!
print "VAL IS: $val\n";
sub do_something {
my $i = shift;
print "Doing something with thread $i!\n";
{
lock $val;
$val = "SOMETHING IS $i";
print "$val\n\n";
}
}
Output:
Doing something with thread 1!
SOMETHING IS 1
Doing something with thread 2!
SOMETHING IS 2
Doing something with thread 3!
SOMETHING IS 3
Doing something with thread 4!
SOMETHING IS 4
Doing something with thread 5!
SOMETHING IS 5
VAL IS: SOMETHING IS 5
How can I get this effect without making $val accessible to the whole script? In other words, how can I make it so attempting to print VAL IS: $val will fail, but the variable will still be successfully shared by the threads?
I can't define it like this:
# Create threads
for my $i (1 .. 5) {
my $val:shared;
threads->create(\&do_something, $i);
}
Or I will get:
Global symbol "$val" requires explicit package
What is the right way to lexically scope a shared variable?
Pass a reference to it as an argument.
sub do_something {
my ($id, $lock_ref) = #_;
print("$id: Started\n");
{
lock $$lock_ref;
print("$id: Exclusive\n");
sleep(1);
}
print("$id: done.\n");
}
{
my $lock :shared;
for my $id (1..5) {
async { do_something($id, \$lock); };
}
}
Or scope it so only the worker subs can see it.
{
my $lock :shared;
sub do_something {
my ($id) = #_;
print("$id: Started\n");
{
lock $lock;
print("$id: Exclusive\n");
sleep(1);
}
print("$id: done.\n");
}
}
for my $id (1..5) {
async { do_something($id); };
}
You can limit the scope of shared variable (make sure that perl sees shared variable before thread creation),
# ..
{
my $val:shared;
sub do_something {
my $i = shift;
print "Doing something with thread $i!\n";
{
lock $val;
$val = "SOMETHING IS $i";
print "$val\n\n";
}
}
}
# Create threads
for my $i (1 .. 5) {
threads->create(\&do_something, $i);
}
# ...

Lex analyzer for generating file not producing a listing of program with lexical error messages

I am attempting to build a lex analyzer that produces a listing of the program with lexical error messages included after the line in which they occur. In other words if the character read cannot start a token it is considered an error. It is also supposed to generate a file with the lexeme-token pairs so that it can verify that the analyzer is working. I can get an output file but it is not working correctly as when I attempt to run it it just gives me a command screen like I'm inside the file working. Here is my code for my scanner file that reads an input text:
%{
#include <stdio.h>
#include <ctype.h>
#include "tokens.h"
void toTitle(char* yytext, int yyleng);
%}
%option noyywrap
ws [ \t\r\n]+
quoted \".*\"
letter [A-Za-z]
digit [0-9]
word {letter}+(\-{letter}+)?
number {digit}+
punc [,:;()]
begin { ECHO; return(begin);}
boolean { ECHO; return(BOOLEAN);}
else { ECHO; return(ELSE); }
end { ECHO; return(END); }
endif void toTitle(char* yytext, int yyleng){ ECHO; return(ENDIF); }
function { ECHO; return(FUNCTION); }
if { ECHO; return(IF); }
is { ECHO; return(IS); }
integer { ECHO; return(INTEGER); }
real { ECHO; return(REAL); }
returns { ECHO; return(RETURNS); }
then { ECHO; return(THEN); }
line [\n]
%%
"&&" { return(LOGOPAND); }
"||" { return(LOGOPOR); }
"!=" { return(LOGOPNOT); }
[ \t\n] ;
{ws} { ECHO; }
"<" { ECHO; return(RELOP); }
"=" { ECHO; return(RELOP); }
"/=" { ECHO; return(RELOP); }
">" { ECHO; return(RELOP); }
">=" { ECHO; return(RELOP); }
"<=" { ECHO; return(RELOP); }
"*" { ECHO; return(MULTOP); }
"/" { ECHO; return(MULTOP); }
"+" { ECHO; return(ADDOP); }
"-" { ECHO; return(ADDOP); }
"true" { ECHO; return(BOOLLITERAL); }
"false" { ECHO; return(BOOLLITERAL); }
{digit} { ECHO; return(I_LITERAL); }
{digit}+"."{digit}* { ECHO; return(R_LITERAL); }
begins { ECHO; return(BEGINS); }
{punc} { ECHO; return yytext[0]; }
{quoted} { ECHO; }
{word} {toTitle(yytext, yyleng); }
{number} { ECHO; }
%%
void toTitle(char* yytext, int yyleng)
{
}
void tokenCount(int token)
{
while (token = yylex())
fprintf(yyout, "%d %s\n", token, yytext);
}
int main() {
while (yylex());
return 0;
}
I have a header file with my defined tokens:
#ifndef TOKENS_H
#define TOKENS_H
typedef enum Tokens {RELOP = 256, ADDOP = 257, MULTOP = 258, LOGOPNOT = 259, BOOLLITERAL = 260, I_LITERAL = 261, R_LITERAL = 262, IDENTIFIER = 263, PUNCTUATION = 264, BEGINS = 265, BOOLEAN = 266, ELSE = 267, END = 268, ENDIF = 269, FUNCTION = 270, IF = 271, IS = 272, INTEGER = 273, REAL = 274, RETURNS = 275, THEN = 276, LOGOPAND = 277, LOGOPOR = 278, begin = 279} Tokens;
#endif
My output is supposed to look something like this:
1 -- Simple program with one function
2
3 function main a: integer returns integer;
4 b: integer is a * 2;
5 begin
6 if a <= 0 then
7 b + b;
8 else
9 b * b;
10 endif;
11 end;
Compiled Successfully
I've noticed that this is third question you've asked on the same problem and suspect that you might not be fully understanding how to complete this task or the documentation and answers you've seen so far. Stackoverflow has guidance and standards on the best ways of forming a question to get the best value and service from the many world class experts available here, such as this guidance on asking questions on StackOverflow. I see that you might be a beginner at this, and in the case of your problem it would have been to your advantage to learn how to simplify the problem. I'll demonstrate how you could simplify the problem, using your code as an example, and thus arrive at a good description of the problem and eventually the solution.
The problem with your code, is the same problem identified in comments by #rici to your earlier question "That lex file looks like it was pasted together from random snippets using different styles".
Let's go back to the flex manual and look at the overall structure of a flex program:
definitions
%%
rules
%%
user code
The position of the %% lines divide the code into three sections, and thus what you put before the %% and what you put after %% is really important.
Now in the answer to your last question #nlu wrote:
ECHO is a special statement, that can only be used in the actions section.
and then you replied:
I rectified the code by moving all the reserved words and their actions to the first part before the %% syntax
Unfortunately you misread that suggestion and left code for the rules/action section in the declaration section. Unfortunately this did not cause flex to give you any helpful messages, as it remained a meaningful flex program; just not the one you were expecting!
To clarify, you cannot have any actions, including an ECHO, before the first %%, because then it would be in the definitions section. They must be after the first %% so the are in the rules/actions section. So, as a consequence, all these lines are in the wrong place:
begin { ECHO; return(begin);}
boolean { ECHO; return(BOOLEAN);}
else { ECHO; return(ELSE); }
end { ECHO; return(END); }
endif void toTitle(char* yytext, int yyleng){ ECHO; return(ENDIF); }
function { ECHO; return(FUNCTION); }
if { ECHO; return(IF); }
is { ECHO; return(IS); }
integer { ECHO; return(INTEGER); }
real { ECHO; return(REAL); }
returns { ECHO; return(RETURNS); }
then { ECHO; return(THEN); }
How could you have debugged this on your own? As its suggests in the SO help pages: simplify. I'll demonstrate by example how that could be done. If you reduced the problem to a language with only one keyword, lets says begin and some whitespace, and deleted all the other lines, for all the other keywords and symbols, then there would be a much simpler problem to address. Lets try this with your code:
%option noyywrap
ws [ \t\r\n]+
begin { ECHO; return(begin);}
line [\n]
%%
[ \t\n] ;
{ws} { ECHO; }
begins { ECHO; return(BEGINS); }
%%
int main() {
while (yylex());
return 0;
}
You will note I have just deleted all the lines that relate to other keywords and symbols as they are confusing the picture with a jumble of extra lines. This is exactly what expert and professional programmers do in their day to day problem solving. You don't think we have some psychic way of finding bugs do you? :-) This is the skill that comes with practise.
Now, focussing on this simpler program, there are things we can see. It does compile and run by the way, and its all your code (just simpler). If we run it, the keyword begins gets ECHOed but the keyword begin does not. There is a clue there. If the line for begin was moved to below the %% it would work just as the begins line did. But why did flex accept the bad program and not give you a helpful error? This is because that line is still a valid definition of a lexeme according to flex regular expression notation. What you defined was a lexeme called begin (which you access using the notation {begin} in the rules section) which is defined as matching the string "{ ECHO; return(begin);}". However, as you never typed that string, and also never used the name {begin} that fragment of definition never gets used.
There is also the question: Does your language really have a keyword called begin and another one called begins. Seems fishy to me. Another bug perhaps?
Similarly we cans see the same with the white space. You have tried to match a newline \n in three places. This is going to be confusing, as you cannot be sure which of the definitions and actions flex will perform when encountering a newline. As you want to number the lines at some point this might be a problem for you. You've also told it to both ignore and ECHO whitespace. Which is it to be? It cannot do both. From your example output, perhaps you wanted them echoed. Making all these fixes to the simple program we get this:
%option noyywrap
ws [ \t\r]+
line [\n]
%%
{ws} { ECHO; }
begin { ECHO; return(BEGIN); }
%%
int main() {
while (yylex());
return 0;
}
which works for a simple language with only the keyword begin. All we now have to do is put the other bits back in, slowly and carefully. Next, lets add the keyword endif to the code, and we get:
%option noyywrap
ws [ \t\r]+
line [\n]
%%
{ws} { ECHO; }
begin { ECHO; return(BEGIN); }
endif void toTitle(char* yytext, int yyleng){ ECHO; return(ENDIF); }
%%
int main() {
while (yylex());
return 0;
}
However, this does not compile. The piece of code void toTitle(char* yytext, int yyleng) looks like an erroneous paste, when you were hacking the code together from other peoples solutions -- doh!.
Now, that has dealt with all the faults in your code, and if you understood them you could get all your code working. Now, there is a bit more programming to do before you have completed the whole assignment. You need to add line counting, handling of variables and constants, and a few other bits and then you are done.
I hope you found that helpful, and leads to you being able to solve the rest of your coding exercise.

AWK file multiline command not working

I have an awk file get_PV_sql_from_file.awk:
#! /bin/awk -f
/^CREATE.*VIEW.*PV_/
{
inside_create = 1; print "view found"
}
{
if(inside_create == 1)
{
print $0
}
}
/.*;$/
{
if(inside_create == 1){
inside_create = 0;
}
}
And when i run it:
awk -f get_PV_sql_from_file.awk test_PV_sql.txt
I have got "view found" phrase in each line:
view found
CREATE FORCE VIEW "POSC"."P3V_SEC_TREES_V" ("BSASC_ID", "BSASC_S", "LV0_K", "LV0_V", "LV1_K", "LV1_V", "LV2_K", "LV2_V", "LV3_K", "LV3_V", "LV4_K", "LV4_V", "LV5_K", "LV5_V") AS
view found
SELECT DISTINCT
view found
B1.BSASC_ID,
view found
B2.BSASC_S,
view found
R_SEC_TREES.LV0_K,
view found
R_SEC_TREES.LV0_V,
...
etc
But if i write each command in awk file on a single line:
#! /bin/awk -f
/^CREATE.*VIEW.*PV_/ { inside_create = 1; print "view found" }
{ if(inside_create == 1) { print $0 } }
/.*;$/ { if(inside_create == 1) { inside_create = 0; } }
It is works right:
view found
CREATE FORCE VIEW "POSC"."PV_SEC_MODULES_V" ("BSASC_ID", "MODULE", "ACT") AS
SELECT DISTINCT
B1.BSASC_ID BSASC_ID,
BSASC_PRIVILEGE.GDLN_OR_PRIV_ID MODULE,
BSASC_PRIVILEGE.R_BSASC_PRIV_KIND ACT
...
etc
Why is this happening? And where i made mistake?
You need to put the pattern and the opening brace that begins the action on the same line. Otherwise the pattern is treated as not having any action, so the default action, print the line, is performed. The action on the next line is then treated as having no pattern which means it matches every line. So write your AWK code like this:
/^CREATE.*VIEW.*PV_/ {
inside_create = 1; print "view found"
}
{
if(inside_create == 1)
{
print $0
}
}
/.*;$/ {
if(inside_create == 1) {
inside_create = 0;
}
}

Zend extension, get arguments of echo?

We have made a Zend extension which we want to write the addresses of the zval's echo is supposed to write out, but we cannot figure how to receive them because we have noticed that there is difference between echo "test"; and $a = "test"; echo $a;
.... Some stuff that overrides the echo opcode ....
FILE *tmpfile;
int echo_handler(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = execute_data->opline;
tmpfile = fopen("/tmp/echo.test","a+");
fprintf(tmpfile,"Echo was called\n");
fclose(tmpfile);
return ZEND_USER_OPCODE_DISPATCH;
}
How do we get the arguments no matter if it is a variable or not?
The handler for echo is
static int ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
zval z_copy;
zval *z = &opline->op1.u.constant;
if (IS_CONST != IS_CONST &&
Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
zend_std_cast_object_tostring(z, &z_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
zend_print_variable(&z_copy);
zval_dtor(&z_copy);
} else {
zend_print_variable(z);
}
ZEND_VM_NEXT_OPCODE();
}
from Zend/zend_vm_execute.h, and as you can see all it basically does is to call zend_print_variable().
Hook that function and you should be on the right track.
Bonus: it works for print statements too.

Resources