Tag Info

New answers tagged

1

I suggest using Perl instead, as it comes preinstalled on most Unix systems: $ echo '104_Fri' | perl -p -e 's/^([0-9]+)_([A-Za-z]+)$/$1;$2/' You can simplify that further: $ echo '104_Fri' | perl -p -e 's/^(\d+)_([a-z]+)$/$1;$2/i' Note: If your input is really as simple as in the question, a simple tr will do: $ echo '104_Fri' | tr '_' ';' Or with ...


0

Another awk variation awk '{ORS = /\\/? "": RS; sub(/\\$/, ""); print}' file


3

Add the -r option ;-) for extended regexps, and the need to \ active content diminishes. $ echo "104_Fri" | sed -re 's/^([0-9]+)_([A-Za-z]+)$/\1;\2/' 104;Fri As the Q is written, (no background data) the splitting-task could be done in several other simpler ways: $ echo "104_Fri" | tr '_' ';' 104;Fri $ echo "104_Fri" | sed 's/_/;/' 104;Fri ... to ...


1

tr -s '\t\nI' ' \n' <<\DATA |\ sed 's/^/I/;s/ */\n/;s/ *[0-9]/,&/g' ID1 1 5 6 8 ID2 1 4 5 7 DATA OUTPUT ID1 1, 5, 6, 8 ID2 1, 4, 5, 7 First tr translates all tabs and newlines into spaces and all capital Is into newlines. It also squeezes repeats. That makes it really easy because at this point it passes to sed input that ...


3

sed '/^[0-9]/{:a;s/[\t\n ]\+/,/g;N;/\n[A-Z]/!ba;}' will do the stuff. Explanation: /^[0-9]/ will match only to lines started with number and apply command group to it {} command group to apply {:a;s/[\t\n ]\+/,/g;N;/\n[A-Z]/!ba;} will read in cycle line by line and replace all spaces, tabs and newlines to comma until line started with letter.


1

I would go for awk, that provides more control and generalizes the problem: awk 'BEGIN{FS="\t"; OFS=","} /^[^A-Z]/ {for (i=1; i<=NF; i++) {if (!a) a=$i; else a=a OFS $i} next} {if (a) print a; a=""; print} END{print a}' Explanation BEGIN{FS="\t"; OFS=","} set input field separator as tab and output field separator as comma. /^[^A-Z]/ ...


1

You should be able to achieve that as follows: if the current line starts with a digit, append the next line into pattern space and then replace sequences of spaces, tabs and newlines with comma-space: $ sed '/^[0-9]/{N;s/[ \t\n]\+/, /g}' file ID1 1, 5, 6, 8 ID2 1, 4, 5, 7


2

Another aspect: How maintainable are the [long] items above? The shorter and more distinct you can keep the clauses, the easier they will be to change and enhance as time passes and (sed-external) facts change around the the function they provide. e.g. sed \ -e 's/[minimal-s1]/[minimal-r1]/' \ -e 's/[minimal-s2]/[minimal-r2]/' \ -e ...


2

You can also break that up this way: sed '/[long1][long2]/ s//[long3][long4]/' Or maybe like: sed "$( printf 's/[%s][%s]/[%s][%s]/' \ long1 \ long2 \ long3 \ long4 )" Or with a heredoc: sed -f - <<SED file.txt s/\ [long1]\ [long2]\ /\ [long3]\ [long4]\ / SED


5

sed 's'/\ '[long1]'\ '[long2]'\ '/'\ '[long3]'\ '[long4]'\ '/' file.txt Splitting on several lines with backslash does work if new lines are not indented. $ echo "a,b" | sed 's/\(.'\ > '\),\(.\)/\2-\1/' b-a Tested on Cygwin with GNU sed 4.2.2


4

You might also alternate addresses. You wind up using far fewer crazy backslashes that way. sed -n '/._./{/^[0-9]*.[A-Za-z]*$/s/_/;/p;}' sed -n '/[^0-9].*_.*[^A-Za-z]/d;/._./s/_/;/p'


5

You can save long string to bash variables, then use in sed command: string=[long1][long2] replace= [long3][long4] sed -e 's/'"$string"'/'"$replace"'/' file If you can use perl, you can break long pattern with x modifier: perl -e 's/ [long1] [long2] /[long3][long4]/x' file


10

Backslash the +: $ echo "104_Fri" | sed 's/^\([0-9]\+\)_\([A-Za-z]\+\)$/\1;\2/' 104;Fri Note that + is not a standard basic regular expression metacharacter, and so doesn't have portable behaviour in sed even when backslashed. You should use sed -r or sed -E to enable extended regular expressions instead, in which you don't need to backslash any of these ...


7

You must escape plus symbol +, too: $ echo "104_Fri" | sed 's/^\([0-9]\+\)_\([A-Za-z]\+\)$/\1;\2/' 104;Fri


1

awk -F "\t" '$4 == "calc" {$4 = $3-$2}1' OFS='\t' file


1

You can use awk: $ awk 'sub(/\\$/,""){printf("%s", $0);next}1' file "abc def xyz pqr"


1

while read twolines do printf %s\\n "$twolines" done <file ...which is what I suspect was the intended destiny for that file anyway. With sed you might do: sed 'N;s/\([^\\]\)\\\n/\1/;P;D' <file ...which would at least protect backslash quoted quotes, though it misses backslash quoted backslash quoted quotes. Yeah, it's kind of a nightmare ...


6

Sed can't do arithmetic┬╣. Use awk instead. awk ' $4 == "calc" {sub(/calc( |\t)/, sprintf("%-6.2f", $3 - $2))} 1' The 1 at the end means to print everything (after any preceding transformation). Instead of the text substitution with sub, you could assign to $4, but doing so replaces inter-column space (which can be any sequence of spaces and tabs) ...


0

The shorter solution seems to be with perl: perl -pe 's/\\\n//'


7

You should be able to use sed -e :a -e '/\\$/N; s/\\\n//; ta' See Peter Krumins' Famous Sed One-Liners Explained, Part I, 39. Append a line to the next if it ends with a backslash "\".


0

awk -F"[:=]" -vRS='+' '{for(i=1; i<=NF; i++) {if($i == "prop1") I=$(i+1); if($i == "prop2") O=$(i+1)}; printf "input: %s -> output: %s\n", I, O}' file


2

sed -n '/ID.* s/p;//,/ID/{//!p;}' <<\DATA ID number1 string DS item11 DS item12 ID number2 not_string DS item21 DS item22 ID number3 string DS item31 DS item32 DATA That relies on this POSIX defined behavior for sed regex addresses: If an RE is empty (that is, no pattern ...


3

If I understand right, I change the not_string in your input for test: ID number1 string DS item11 DS item12 ID number2 qwerty ...


1

In all of these, /141.299.99.1/ will also match (e.g.) 141a299q99+1 or 141029969951 because . in a regular expression can represent any character. Using /141[.]299[.]99[.]1/ is safer, and you can add additional context at the beginning and end of the whole regexp to make sure it doesn't match 3141., .12, .104 , etc.


1

To do it without grep and assume that you don't have duplicated lines, you can: $ sort 20000-words.txt 50000-lines.txt | uniq -u or: $ comm -23 <(sort 50000-lines.txt) <(sort 20000-words.txt)


9

Assuming that 20000-words.txt is already in the format of one word per line, do: grep -vFf 20000-words.txt 50000-lines.txt >50000-filtered-lines.txt The -f argument to grep tells it to read patterns from a file, one pattern per line, instead of taking them as command line arguments. The -F argument to grep tells it that the patterns should be used as ...


0

Here is an awk solution: $ awk -F '/|:' ' $3 == "8013765024" {flag = 1} $0 == ",11:1" && flag {$2 = 2;flag = 0} 1 ' OFS=':' file


3

Here's an attempt to emulate grep -B3 using a sed moving window, based on this GNU sed example (but hopefully POSIX-compliant - with acknowledgement to @St├ęphaneChazelas): sed -e '1h;2,4{;H;g;}' -e '1,3d' -e '/141\.299\.99\.1/P' -e '$!N;D' file The first two expressions prime a multi-line pattern buffer and allow it to handle the edge case in which there ...


4

If your system doesn't support grep context, you can try ack-grep instead: ack -B 3 141.299.99.1 file ack is a tool like grep, optimized for programmers.


8

With sed you can do a sliding window. sed '1N;$!N;/141.299.99.1/P;D' That does it. But beware - bash's insane behavior of expanding ! even when quoted!!! into the command string from your command history might make it go a little crazy. Prefix the command with set +H;if you find this is the case. To then re-enable it (but why???) do set -H afterward. ...


3

You can implement the same basic approach as the other non-grep answers in the shell itself (this assumes a relatively recent shell that supports =~): while IFS= read -r line; do [[ $line =~ 141.299.99.1 ]] && printf "%s\n%s\n%s\n%s\n" $a $b $c $line; a=$b; b=$c; c=$line; done < file Alternatively, you could slurp the whole file into ...


3

When available you can use pcregrep: pcregrep -M '.*\n.*\n.*\n141.299.99.1' file


2

awk '/141.299.99.1/{for(i=1;i<=x;)print a[i++];print} {for(i=1;i<x;i++) a[i]=a[i+1];a[x]=$0;}' x=3 filename In this awk solution, an array is used which will always contain 3 lines before the current pattern. Hence, when the pattern is matched, the array contents along with the current pattern is printed. Testing -bash-3.2$ cat filename ...


3

Since you mention that you don't have the -B option to grep, you can use Perl (for example) to make a sliding a window of 4 lines: perl -ne ' push @window,$_; shift @window if @window > 4; print @window if /141\.299\.99\.1/ ' your_file Ramesh's answer does a similar thing with awk.


10

grep will do a better job of this: grep -B 3 141.299.99.1 TESTFILE The -B 3 means to print the three lines before each match. This will print -- between each group of lines. To disable that, use --no-group-separator as well. The -B option is supported by GNU grep and most BSD versions as well (OSX, FreeBSD, OpenBSD, NetBSD), but it is technically not a ...


0

With bash: #!/bin/bash while read LINE do if [[ "$LINE" =~ '<' ]]; then echo -e "${LINE/>*</>\\n<}"; fi done < file.html


2

Using an actual html parser isn't that hard: perl -MHTML::Parser -E ' $handler = sub {say "<".shift.">"}; HTML::Parser->new(start_h => [$handler,"tag"], end_h => [$handler,"tag"]) ->parse_file(shift @ARGV) ' file.html <html> <head> <title> </title> </head> <body> </body> ...


3

A quick hack with perl: perl -wlne 'print for(/<.*?>/g)' file.html But for a serious solution you should use a tool that really understands html/xml.


1

Below mentioned solution might help: cat file_name.txt | fmt -w 80 > reduced_file_name.txt fmt - simple optimal text formatter.


3

Use fmt instead: fmt --width=80 file From man fmt: -w, --width=WIDTH maximum line width (default of 75 columns)


2

In additional to @Homer's answer, from perldoc perlrun: specifies that files processed by the "<>" construct are to be edited in-place. It does this by renaming the input file, opening the output file by the original name, and selecting that output file as the default for print() statements. The extension, if supplied, is used to modify ...


13

sed creates a temporary file, writes the output into that file, and then renames the temporary file over the top of the original. You can watch what happens using strace: $ strace -e trace=file sed -i -e '' a execve("/usr/bin/sed", ["sed", "-i", "-e", "", "a"], [/* 34 vars */]) = 0 <...trimmed...> open("a", O_RDONLY) = 3 ...


4

GNU sed is bundled with releases newer than Solaris 10. Otherwise, you can easily build it from source or retrieve it from opencsw or other freeware repositories. Solaris 10 packages are listed in this pdf: http://docs.oracle.com/cd/E19253-01/pdf/817-0545.pdf


0

You could match any initial space-separated sequence of pairs of hex digits into a substitution group, and then just re-substitute that group, e.g. sed -r 's/^(([[:xdigit:]]{2}\s+)+).*$/\1/'


0

sed -e '/^precalculated/!s/^\(.\{47\}\).*$/\1/' < h This keeps first 47 characters on any line not matching precalculated at the beginning. Lines matching are just copied.


5

An ugly way of doing this (i.e. causing a function call in shell based on output from awk) could look like this: awk -F '\t' ' FNR < 2 {next} FNR == NR { for (i=2; i <= NF; i++) { if (($i == 1) || ($i == 4)) printf "retrieve %s\n", $i if (($i == 2) || ($i == 2)) printf "retrieve2 ...


0

I found this pattern: sed -e 's/^\(..\s.\{45\}\).*/\1/'


0

You can group the expression and use \1 to point to the group. E.g sed 's/^\($RELEASE.*=\).*/\1 '"'1234'"'/' config.ini


2

I don't have any problem with [[:space:]]. Here's a really silly little example showing the mixed-replacement of spaces and tabs: $ echo -e 'A \t \t B' | sed 's/A[[:space:]]*B/WORKED/' WORKED You can also use \s which is often preferable with big sed strings because it's much shorter: $ echo -e 'A \t \t B' | sed 's/A\s*B/WORKED/' WORKED Anyway, I ...


4

If the existing commented lines form a single contiguous block, then you could match from the first commented line instead, commenting-out only those lines up to and including your end pattern that are not already commented sed '/^#/,/dotan/ s/^[^#]/#&/' file If the existing comments are not contiguous, then due to the greedy nature of the sed range ...



Top 50 recent answers are included