New answers tagged

0

Thank you! worked like a charm! Appreciate your help.


1

For each line you can just use substr($line,30,2) to get the two characters you want. So something like #!/usr/bin/perl use warnings; use strict; open(my $file1,">file1"); open(my $file2,">file2"); open(my $file3,">file3"); while(<>) { my $ch=substr($_,30,2); if ($ch eq '0A') { print $file1 $_; } elsif ($ch eq '0B') { print $file2 ...


5

You can use arithmetic instead of string manipulation for this: awk ' function neg(x) {if (x<0) return x; else return -x} /Columnaxis/ {print neg($2)} ' file works with values like "100" or "+100" or "-100" etc.


1

With GNU grep: grep -oP 'Columnaxis:.*?\K\d+' file | sed 's/^/-/' For example: $ cat file Columnaxis: 100 Columnaxis: -5 $ grep -oP 'Columnaxis:.*?\K\d+' file | sed 's/^/-/' -100 -5


5

Or awk alone: $ cat text.dat Columnaxis: 100 Columnaxis: +100 Columnaxis: -100 $ awk '/Columnaxis/ { gsub("-|+", "", $2); print "-"$2 }' text.dat -100 -100 -100


3

You can do this using sed alone: sed -nE 's/^Columnaxis:[[:blank:]]+-?([0-9]+)$/-\1/p' file.txt Example: $ cat file.txt Columnaxis: 100 Columnaxis: -100 asdklasjds $ sed -nE 's/^Columnaxis:[[:blank:]]+-?([0-9]+)$/-\1/p' file.txt -100 -100


0

If your fields never contain commas, you could try: $ perl -F, -lane '@k=split(/["|]/,$F[6]); @l=grep{/^10\./}@k; print "$F[0] @l"' file | sed 's/"//g' STRING1 10.224.241.219 STRING2 10.230.16.188 STRING3 10.226.41.43 STRING4 10.226.41.43 STRING5 10.20.40.6 10.226.41.43 Explanation Perl's -a option makes it work ...


0

On GNU system: $ NL=' ' $ <file xargs -n4 -d "$NL" sh -c 'printf "%s\n" "$@" | sort' sh world1.com /randomkeygahjuh572/key639839 world2.com /randomkey788gauh72/key63whjk world3.com /randomkey788gauh72/key63whjk world4.com /randomkeyhghgdh778/key67567 world1.com /randomkeyhueh34778/key67uuu77 world2.com ...


1

$ awk '{l=l+1; ln[$1]=$0; if (l%4==0) { \ printf ("%s\n%s\n%s\n%s\n", ln["world1.com"], ln["world2.com"], ln["world3.com"], ln["world4.com"]); \ delete ln; l=0; } } ' test.txt world1.com /randomkeygahjuh572/key639839 world2.com /randomkey788gauh72/key63whjk world3.com /randomkey788gauh72/key63whjk world4.com ...


2

With perl: perl -n -e 'if (m/^Trailer/) {print "\n"} else {chomp; print $_," "}' arun.txt Output: Hdr1 Dtl1.1 Dtl1.2 Dtl1.3 Dtl1.4 Hdr2 Dtl2.1 Dtl2.2 Dtl2.3 Dtl2.4 Dtl2.5 HdrN DtlN.1 DtlN.2 DtlN.3 Note: the output has a trailing space character on each line. If you don't want that, get rid of it by piping the output through sed -e 's/ $//'. Or use ...


1

#!/usr/bin/perl use strict; use warnings; use autodie; use open qw< :encoding(ASCII) >; my $filename = $ARGV[0]; my ($ip_fh, $op_fh); open($ip_fh, "<", $filename); open($op_fh, ">", "$filename".".sorted"); my @ip_lines = <$ip_fh>; for(my $i = 0; $i <= $#ip_lines; $i++) { print $op_fh sort @ip_lines[$i..($i+3)]; $i += 3; } ...


1

This perl script should work with any number of domains (first fields) with any number of keys (second fields) per domain. Domains may have the same number of keys each, but don't have to. It builds up a hash (%domains) with each element of the hash containing an array of keys. While doing that, it keeps track of the largest number of keys seen for any of ...


4

To organize the files by world: $ paste -d'\n' <(grep world1 file) <(grep world2 file) <(grep world3 file) <(grep world4 file) world1.com /randomkeygahjuh572/key639839 world2.com /randomkey788gauh72/key63whjk world3.com /randomkey788gauh72/key63whjk world4.com /randomkeyhghgdh778/key67567 world1.com ...


0

Use a shell loop and ex! { for i in {1..50}; do printf %s\\n '0/old/s//new/'; done; echo x;} | ex file.txt Yes, it's a bit goofy. ;) Note: This may fail if there are less than 50 instances of old in the file. (I haven't tested it.) If so, it would leave the file unmodified. Better yet, use Vim. vim file.txt ...


3

Since arithmetic is required, sed is not the right tool. The solution below uses awk. Answer for revised question You say the unwanted hashes always have names that include a number followed by a letter. In that case: $ awk '/^interface .*[[:digit:]][[:alpha:]]/{$0="interface ethernet" ++f} 1' file1 ! interface ethernet1 xxxx yyyy zzzz ! interface ...


4

Anchor the text in the regex sed -i '/^name$/d'


2

With gnu sed: sed -Es '/pattern1|pattern2|pattern3/{ s/.*:[[:blank:]]*//;H} $!d;x;/^\n$/d;s/\n(.*)/\1,/;s/\n/,/g' folder/*.txt > list.txt where list.txt content will be something like: file1match1,file1match2, file2match1, file4match1,file4match2,file4match3, so file3 is missing from the output as there was no line matching pattern*. How it works: ...


1

Here's a shorter answer that uses fold then shifts its output by 11 spaces. To see what it is doing add a -v or -x to the final bash. | sed 's:\(.*\)---\(.*\):printf "%-10s " "\1";fold -w '$(($COLUMNS - 11))' -s <<\\!|sed "1!s/^/ /"\n\2\n!\n:' | bash


4

OK, first of all do not use a for loop! That is very inefficient. Just give grep all the file names at once: grep 'sometext:' folder/*.txt In this case, however, I would use awk instead of grep. I made 10 copies of your input file to test: $ awk '{ if($1~/sometext|someothertext|somedifferenttext/){ printf "%s,",$2 } ...


3

Here's an awk script that stores the whole file in memory: awk '{line[NR]=$0} END {for (i=NR; i>=1; i--) print line[i]}' file Phrased as a shell function: tac () { awk '{line[NR]=$0} END {for (i=NR; i>=1; i--) print line[i]}' "$@"; }


1

Here's a clean clear-cut POSIX solution for on-disk files: #!/bin/sh function tac () { lines=$(wc -l < "$1") while [ $lines -gt 0 ] do head -n $lines "$1" | tail -n 1 lines=$((lines-1)) done } The main down-side is that it reads the file once for every line in the file. POSIX doesn't specify an upper limit for -n number, so large files ...


2

This use case just begs for using ex. Unfortunately, since deleting the third line after a given line may delete a line containing PATTERN and thus cause the deletion associated with that line to be skipped (or worse, to delete the incorrect line), you need to reverse the file using e.g. tac first. Then you can delete the third line before each instance of ...


2

You can do this with a sed one-liner as follows, though it is certainly not readable for the "uninitiated": sed -n '1h;1!{x;H;};${g;p;}' file.txt Explanation: -n suppresses sed's default action of printing each line. 1h causes the first line to be stored in the hold space. 1!{...} applies this block of commands to all lines except for the first one. ...


2

for f in file1 file2 file...; do sed -i -f <(grep -n PATTERN "$f" | while IFS=: read line rest; do printf "%dd; " $((line+3)); done) "$f" done To split that apart: Loop over file1 file2 file... build up a sed expression inside the process substitution, to eventually run against the file. grep outputs line numbers matching PATTERN in the file (along ...


2

I like a 2-pass mechanism so we can use sed -i: for file in file1 ... do sed -i "$file" -e "$(awk <"$file" -v N=3 '/PATTERN/{ print (NR+N) "d" }')" done


6

You could use awk for this I believe like so: awk -vN=3 '/PATTERN/ {skips[FNR+N]=1;} {if(!(FNR in skips)) print;}' <file> so each time we hit PATTERN we'll record the line that is N away from here, and only print those lines we have not marked for skipping. with gawk you could use -i inplace as well to do it in place As you noted, that wouldn't ...


13

This perl script builds a hash with words (read one per line from stdin, and/or from any filenames listed on the command line) as keys, and syllable counts as the values. Then it prints the hash keys, sorted by the syllable counts. #! /usr/bin/perl use strict; use Lingua::EN::Syllable; my %words = (); while(<>) { chomp; $words{$_} = ...


2

There are carriage returns at the end of $i, because there are carriage returns at the end of the lines in all.txt. It was probably produced on Windows: Windows uses the two-character sequence CR,LF to mark a line break, whereas Unix (and most of the rest of the world) uses just LF (linefeed, synonym of newline in the Unix world), so Unix sees a line with a ...


-1

Your error message indicates that sed is getting an argument of /log.dat - neither $i or $in are set to any value. I think you have a blank line in your All.txt file. /log.dat: No such file or directory #(then the path to this file)


0

PATH_TO_FOLDER="/some/path/to/folder/" FILE_EXTENSION=".ext" FILES=$(ls ${PATH_TO_FOLDER}/*${FILE_EXTENSION}) for FILE in $FILES; do FILENAME=$(basename $FILE ${FILE_EXTENSION}) TMP_FILE=${PATH_TO_FOLDER}/${FILENAME}.tmp awk -v Lines=2 '{if($0~"radius-server"){ print; for(i=0;i<=Lines;i++) { getline; if(i==Lines){ next; }else{ print; } } } else{ ...


0

$ FLAG=$(awk -F\| '{printf("%s, ", $1)}' file1.txt) $ echo $FLAG 1234, 1345, 8427, 2132, 3243, $ sed "s/FLAG/${FLAG%%, }/" select.sql SELECT * FROM CUSTOMERS WHERE ID IN (1234, 1345, 8427, 2132, 3243); This depends on the flag list being small enough to fit on the command line. If it's not, you can use getline in awk to process file1.txt, gathering ...


2

Even though this is an old question, it seems to me it's a perennial question, and a more general, clearer solution is available than has been suggested so far. Credit where credit is due: I'm not sure I would have come up with it without considering Stéphane Chazelas's mention of the <> update operator. Opening a file for update in a Bourne shell ...


1

sed seems like the right tool: sed -i '/radius-server/!b;n;n;d' filename How it works: /radius-server/!b # as long as it's NOT 'radius-server' do nothing (branch to end) n # read next line (replace current line with next line) n # same as above - we now read 2 lines d # delete the current line UPDATE - to modify multiple files, simply use glob ...


1

Unless you have GNU awk 4.1.0 or later... You won't have such an option as sed's -i option so instead do: for file in * do awk -v lines=2 'BEGIN { ignore = -1 } /radius-server/ { ignore = NR + lines } NR != ignore { print }' "$file" done > result.txt This works as follows: BEGIN { ignore = -1 } # initialize ignore with -1 so NR will never ...


3

With gnu awk you can do something simple like this: awk -F '---' ' { gsub(/.{50,60} /,"&\n ",$2) printf "%-10s %s\n", $1, $2 }' For a more accurate long-winded version handling long words: awk -F '---' ' { printf "%-10s ", $1 n = split($2,x," ") len = 11 for(i=1;i<=n;i++){ if(len+length(x[i])>=80){printf "\n "; ...


0

#! /bin/ksh inputfile='file1.txt' sqlfile='select.sql' S_ids=$(awk -F"|" '{gsub(/^|$/,"\\'\''",$1) ; print $1","}' "$inputfile" | xargs | sed -e 's/,$//') sed -i "s/FLAG/${S_ids}/g" "$sqlfile" Output: $ cat select.sql SELECT * FROM CUSTOMERS WHERE ID IN ('1234', '1345', '8427', '2132', '3243'); This uses awk's gsub() function ...


2

The reason this doesn't work can be inferred from the error message (that you omitted to provide): sed: -e expression #1, char 14: unterminated `s' command The sed command does not accept a multi-line value. You have to collapse your multiple lines into a single line. You could do this with a script such as this: #!/bin/ksh S_ids="'$(cut -d'|' -f1 ...


1

The following should work with python 2 and 3, save as xyz.py and run with python xyz.py file_1 file_2 file_3: import sys import csv names = set() files = {} for file_name in sys.argv[1:]: b = files.setdefault(file_name, {}) with open(file_name) as fp: for line in fp: x = line.strip().split() names.add(x[1]) ...


0

There are 2 ways I recommend going about this. 1) Put a function in your bashrc / bash_profile and create an alias to call that function (this will make global usage of this) 2) create a shell script file and can create an alias of that file as well. #!/bin/bash function matchString(){ REGEX="$1" FILE="$2" RESULTS=$(grep -n "$REGEX" $FILE | awk -F ":" ...


0

Try this awk. echo "ABC123xxx:: 2345 ABC345yyy:: 5678 ABC986zzz:: 7955" | awk '{for(i=1;i<=NF;i++) if(match($i,"ABC")>0) line=line "\n"$i;else line=line $i; sub("^\n","",line); print line}' Creates a line with all fields, adding in front of the fields that begin with "ABC" a line break. Finally it eliminates the first line break and prints


0

sed -E -e 's/ (ABC)/\n\1/g' The sed command replaces any instance of ABC with a newline followed by ABC. It uses the () to capture part of the match (ABC without the leading space) and \1 to include it in the replacement. e.g. $ echo 'ABC123xxx:: 2345 ABC345yyy:: 5678 ABC986zzz:: 7955'| sed -E -e 's/ (ABC)/\n\1/g' ABC123xxx:: 2345 ABC345yyy:: 5678 ...


0

With sed: $ sed -e 's/ ABC/\ ABC/g' <file ABC123xxx:: 2345 ABC345yyy:: 5678 ABC986zzz:: 7955


0

perl -00 -n -e 'print if (m/select /i)' XXARXADLMT.txt This uses perl's paragraph-reading mode (-00 option) to print only the paragraphs matching the case-insensitive regular expression select (with a trailing space). "paragraphs" are blocks of text separated by 1-or-more blank lines. Output: select * from emp; select * from dept; (there is ...


0

This is a small improvement to Gilles awk solution (thanks Gilles!), but does require nawk: nawk '{if (/\\$/) {$0=substr($0,1,length($0)-2); printf "%s",$0} else print}' This will create a continuous line if the line wraps, but does not include the "\" and space character. (I found this helpful when grepping for PATH statements since the "\" can lead to ...


0

RedGrittyBrick has - pointed - out the pitfalls of trying to parse HTML reliably. If, however, your HTML is as well-formatted as you show, then this may do the job: expr= while read -r one two rest do expr="$expr; s/<uniquetag>$two<\/uniquetag>/<uniquetag>$two - $one<\/uniquetag>/" done < file2 sed "$expr" sourcehtml > ...


2

With vim there is more than one way to do it: 1 - Visual selection A more detailed explanation of Mikhail Krutov comment about visual selection: /Directory to find the first match Shift + v (visual mode) /Directory> to select all(select until find Directory> You can also hit } twice to select 2 paragraphs instead of using the search. ...


1

With perl, it's as easy as: perl -pe 'if ((/<Directory/ && !$done) ... /<\/Directory/) { $done = true; s/^/#/; }' < config_file The trick is the three-dots operators (the two-dots works also as long as <Directory> and </Directory> are not in the same line). /<Directory/ ... /<\/Directory/ matches all line between these ...


0

Assuming that your entries are always separated by exactly one blank line, you can do the following: awk 'BEGIN{RS="\n\n"; FS="\n"; OFS="\n"; ORS="\n\n";} {if ($1 ~ /\<select\>/) {print};}' file.txt Input file: select * from emp; select * from dept; selection end; select something more selected wrong select again * from class; Output: ...


0

If commands are ended by ; you could: awk -v RS=";" '/from/' file If you want just the table names after "from" you can try perl -0nE 'say join(";", /from\s+(\w+)/ig)' file


0

As Ziggy says, is not very clear what you need but maybe this AWK will do. awk ' /select \*$/{flag=1;print;next}/selection/{flag=0}flag' file.txt



Top 50 recent answers are included