Hot answers tagged

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{$_} = ...


7

If you want column 3 to be exactly '1', then: awk '$3==1' input > output If you want column 3 to contain '1', then: awk '$3~1' input > output In case you prefer sed, here's one for "column 3 is exactly 1": sed -rn '/^[^ ]*[ ]*[^ ]*[ ]+1$/ p' input > output ... and sed for "column 3 contains 1": sed -rn '/^[^ ]*[ ]*[^ ]*[ ]+.*1.*$/ p'


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 ...


4

Assuming there's no whitespace after the third column (i.e. the number is at the very end of the line) and that you're only dealing with single digit numbers on the third column: grep '1$' input.txt > output.txt


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 "; ...


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]}' "$@"; }


3

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 } ...


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: ...


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 ...


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


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

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

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 ...


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. ...


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 ...


2

Since it's either all spaces or all tabs you could pipe it to sed 'H;$!d;g;: m;/\n[^\n[:blank:]]/!s/\n[^\n]/\n/g;t m;s/.//' That's gnu sed (I don't think other seds support [\n]). It works by appending each line to the Hold buffer and then deleting it if it's not the last one ($!). On the last line it copies the hold space content over the pattern space ...


2

Posting my comment as an answer to be marked as "solved" for n in $(cat myfile | tr 'a-f' 'A-F');do echo "obase=2; ibase=16; $n" | bc ;done Okay, in the light of what you have said and what I understood, I have a couple of suggestions to you. The first one, converts each hex line into a new binary line and puts a line break at the end of each line. here is ...


2

Something simple like: mapfile -t names < file1 for name in "${names[@]}" do echo "${name}" $(grep -c "^$name " file2) done Will provide output like: Peht 2 Mawo 3 Stso 1 Makr 0 Bavo 2 The grep string says to anchor the username at the beginning (^) of the line, and enforce a trailing space after the line.


2

test.awk: FNR == NR{ names[$1] next } ($1 in names){ ulog[$1]++ } END{ for(name in ulog){ print name ":" ulog[name] } } and run it as awk -f test.awk user.list user.log FNR==NR # does the file record number == the record number, if it does then we are still in the first file next # as we are still in the first file, skip the ...


1

You can reach a good-enough result by using temporary files: my_file=file.txt #or =$1 if in a script #create a file with all the lines to discard, numbered grep -n -B1 -A5 TBD "$my_file" |cut -d\ -f1|tr -d ':-'|sort > /tmp/___"$my_file"_unpair #number all the lines nl -nln "$my_file"|cut -d\ -f1|tr -d ':-'|sort > /tmp/___"$my_file"_all #join the ...


1

You can fix the file using awk like this: awk '/^>/{if(x)t=$0;else print"\n"$0} !/^>/{printf"%s",$0;if(t)print"\n"t} /^>COSN229024/{x=1}' < wrong.fasta > good.fasta After this you will probably also need to fix the beginning and the end of the file manually.


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 ...


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]) ...


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


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 ...


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

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. ...



Only top voted, non community-wiki answers of a minimum length are eligible