Tag Info

New answers tagged

4

You can do it like this: sed -e's/ \([^ ][^ ]\)/\n\1/g' \ -e's/\([^ ][^ ]\) /\1\n/g' \ -e's/ //g;y/\n/ / ' <<\IN I have a source text file containing text where some words are l e t t e r s p a c e d like the word "letterspaced" in this question (i.e., there is a space character between the letters of the word. IN The idea ...


2

A Perl approach that mostly works: perl -C -lpe 's/(?:^|\P{L})\K\p{L}(?:\s\p{L})+(?=\P{L}|$)/$&=~s{\s}{}rgo/goe' This assumes a version of Perl recent enough to know about the /r flag in replacements. Proof of concept: $ echo 'Do I like «ł é t t ê r s p ä c è đ» text?' | perl -C -lpe ...


0

Perl's lookahead assertions make this simple. AFAIK, sed lacks these. Given that two or more whitespaces separate the words, this eliminates single spaces but leaves unaltered sequences of two or more: perl -pe 's/\s(?!\s)//g' myfile The p switch causes Perl to read myfile and then substitute single spaces (\s) which are NOT followed by another space. ...


2

An easy and portable way is to insert a file with an empty line in the file arguments: # create file with one empty line echo > emptyline.txt # calling sed: sed -e 's/%%FOO%%/whatever/g' \ -e 's/%%BAR%%/other thing/g \ file1.ldif.template \ emptyline.txt \ file2.ldif.template \ | ... Some shells support also this: sed -e ...


2

Using GNU sed -s (--separate) extension, you can append an empty newline after each filename (line addresses refer to each filename, instead of treating all the input as one longer stream, similar to awk's FNR and NR variables) sed \ -s \ -e '$a\\' \ -e 's/%%FOO%%/whatever/g' \ -e 's/%%BAR%%/other thing/g \ file1.ldif.template \ ...


2

Another sed: $ sed -e '/X/{ $!N /\n.*Y/!D }' file 31 X 32 Y 33 X 34 Y 36 X 37 Y


3

Using sed: sed -n ':b /X/ { h; n; /Y/! b b; H; x; p; }' Output: 31 X 32 Y 33 X 34 Y 36 X 37 Y


1

One approach is to pick a different delimiter besides /. For example, using |: sed -ie "s|queue_directory = /var/spool/postfix-secondary|queue_directory = /var/spool/postfix-$newnumber|g" /etc/postfix-$newnumber/main.cf Another approach is to backslash-escape your other slashes: sed -ie "s/queue_directory = ...


4

{ nl -s\; -w1 -ba | sort -t\; -k2,2 | sed -e:n -e'h;$!N' \ -e's/^\([^;]*\(;[^;]*;\).*\)\n[^;]*\2/\1;/;tn' \ -ex -e:N \ -e's/;/;/6p;tD' \ -e's|$|;N/A|;tN'\ -e:D -ex -eD | sort -t\; -nk1,1 | cut -d\; -f2-; } <in >out So there's a giant pipeline. It works ...


1

There are various tools that can do this. If you have pcregrep (it should be available in your distribution's repository), you can do: $ pcregrep -M 'X\n[^\n]+Y' file 31 X 32 Y 33 X 34 Y 36 X 37 Y The -M switch allows pattern to match across newline characters and the regular expression matches an X, followed by a newline, then any non-newline characters ...


1

If I understand you correctly, you only want lines containing X if they are then followed by a line containing Y, and then you want both lines. grep -A1 X filename |grep --no-group-separator -B1 Y


1

sed -e's/\(\t.*\t\).*PT/\1PT/;t' \ -e's/\t[^\t]*/\tNA/2' That should work for you, though it will only stop stripping chars at the last occurrence of PT in the last field on the line. Also, depending on your sed version, you may have to use literal <tab> characters everywhere I use the \t escape. The gist is to look for two tabs on a line ...


1

This is more easily done using awk in place of sed; in case awk is an option: < input awk 'BEGIN {FS=OFS="\t"} {if ($3~/PT~/) sub(/.*PT~/, "", $3); else $3="NA"; print}' Expanded: BEGIN { FS=OFS="\t" } { if ($3 ~ /PT~/) sub(/.*PT~/, "", $3); else $3 = "NA"; print } BEGIN {FS=OFS="\t"}: sets the field separator1 and ...


3

If you're not tied to sed: awk -v pattern="ABCD" ' BEGIN { FS = OFS = ";" } { # find the first field containing the string for (i=1; i<NF; i++) if ($i ~ pattern) break # alter the last field to the desired contents $NF = $i "/" $NF # shift each subsequent field one place for (;i<NF; i++) $i = ...


3

sed 's/\([^;]*ABCD[^;]*;\)\(.*;\)/\2\1/' <in >out That should probably do it. It will only work for the first occurrence of an ABCD field, though. If there are more than one on the line, all of the rest will be skipped. To swap the last ; semicolon for a forward slash, just alter it a little: sed 's|\([^;]*ABCD[^;]*\);\(.*;\)|\2\1/|' <in ...


2

sed -e's/ *[^ 0-9]*/&\n/6;:n' \ -e's/\(\n[^ ]*\)[^ ]/\1 /;tn' \ -e's/\n//' <infile Here's some sed to do it. The first thing we do is replace the 6th occurrence of one or more spaces followed by a sequence of zero or more [^ 0-9] not-space or numeric characters with itself followed by a newline. Basically this means that if the 7th ...


3

As you want to preserve your columns you can change output field separator to be tab not space for example and it will be easier for further processing if you rely on columns count. So you can use following awk: awk 'BEGIN { OFS = "\t"; }; { if ($7 ~ "^[0-9]*$") $7 = " "; else $7 = $7; }; 1' In BEGIN section we are changing output field separator(OFS) to ...


2

awk '{gsub("^[0-9]*$"," ",$7);$7=$7;OFS="\t";print}' file.txt


0

Perl to the rescue: #!/usr/bin/perl use warnings; use strict; while (<>) { # Process line by line. my @F = split /(\s+)/; # Split the line into @F, keep whitespace as members, too. $F[12] =~ s/./ /g # Replace any character with space if $F[12] =~ /^[0-9]+$/; # if there are just digits. print ...


3

As some different variants awk awk '{$3=A[split($3,A,"-")]}1' file sed sed -r 's/((\S+\s+){2})[^- ]+-/\1/' file


0

Using awk: < input awk 'BEGIN {FS=OFS=" "} {gsub(/[^-]*-/, "", $3); print}'


4

Perl to the rescue: perl -lane 'BEGIN { $, = "\t" } $F[2] =~ s/.*-//; print @F' < file -l appends newlines to print -n reads the input line by line -a splits each line on whitespace and populates the @F array $, separates list members when printed, set it to tab s/.*-// substitutes everything up to a dash with nothing, it's bound to the third column ...


0

I forgot to update this thread. Found the solution same day by using following mysql -u$SQLUSER -p$SQLPASS -e "use $DB; select creationdate,login,package,expirydate,mobile from users WHERE creationdate >= NOW() - INTERVAL 5 MINUTE;"


1

So I took your hex string and printed it out to bytes, but I swapped the NULs for <spaces> (mostly because I can't figure on how to get a NUL in a grep pattern): time \ ( set x58 x5e x20 x20 xfe x5a x1e xda \ x48 x20 x20 x20 x0d x20 x03 x20 \ x07 x20 x20 x20 xcd x01 x20 x20 export ...


1

sed -r ':a;N;s!;N/A!!g;s/^(([^;]*;){3})(.*)\n\1/\1\3;/;T;s!^(([^S][^;]*;){3,})(S*SM-[^;]*);(([^S][^;]*;){1,})(.*)!\1\4\3/\6!;ta' inputfile Even though the implied math of your comment for only 6 fields in the output suggests that there are only pairs, this is the looping version with changes to output SM-1-1/SM-1-2 when matched.


0

You could actually parse the file as a CSV file, and strip extra whitespace: ruby -rcsv -ne ' row = CSV::parse_line($_) puts CSV::generate_line(row.map {|field| field.strip}) ' file 294335,17-APR-15 00:00:00,6258,C,"",07-JAN-15 00:00:00


0

Using awk: < input awk 'BEGIN {FS=OFS=","} {gsub(" ", "", $1); gsub(" ", "", $3); gsub(" ", "", $4); gsub(" ", "", $5); print}' This will have the effect of removing any space character from the 1st, 3rd, 4th and 5th comma-separated field in each record.


4

The GNU implementation of grep (also found in most modern BSDs though the latest versions are a complete (mostly compatible) rewrite) supports a -o option to output all the matched portions. LC_ALL=C grep -ao CDA | wc -l would then count all the occurrences. LC_ALL=C grep -abo CDA to locate them with their byte offset. LC_ALL=C makes sure grep doesn't ...


1

Not sed, but here's a solution using negative lookbehind assertion (?<!...) in perlre. perl -pe 's/(?<!\d\d-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-\d\d) //g'


1

TXR: @(repeat) @ (cases) @id;@f2;@f3;@val1;@nil;@sm1 @id;@f2;@f3;@val2;@nil;@sm2 @ (do (put-line `@id;@f2;@f3;@val1;@val2;@sm1/@sm2`)) @ (or) @line @ (do (put-line line)) @ (end) @(end) $ txr data.txr data D04005;4;279;0;0;SSM-4-1 D04005;5;40;0;0;SSM-5-1 LE040A;1;363;(26.3);(27.4);SM-1-1/SM-1-2


2

sed ':n s|;N/A;|;|g;$!N s|^\(\([^;]*;\)\{3\}\)\(.*\)\n\1|\1\3;|;tn P;D ' <<\IN D04005;4;279;0;0;SSM-4-1 D04005;5;40;0;0;SSM-5-1 LE040A;1;363;(26.3);N/A;SM-1-1 LE040A;1;363;(27.4);N/A;SM-1-2 LE040A;1;363;(28.5);N/A;SM-1-3 LE040A;1;363;(29.6);N/A;SM-1-4 IN That will continue to branch back to test for every sequential in input, merging ...


5

there is a missing -e before s/foo/bar/ (*) there is a confusion, are you (the script) editing index or www/index.js ? if index is a template file (with API_CONTEXT_URL) to be used to produce www/index.js, I would suggest sed -e s,API_CONTEXT_URL,http://localhost:5557,g index > www/index.js note that you can use any chat a separator between ...


2

I'm not sure I decrypted your prose correctly. The script below adds #include <stdint.h> to files in the current directory that (1) contain the word LARGE_INTEGER, and (2) don't already include <stdint.h>: sed -i -e '1i\' -e '#include <stdint.h>' $( egrep -c '#include +<stdint\.h>' $( fgrep -lw LARGE_INTEGER * ) | \ sed ...


3

I'd use1 find with two -exec actions e.g.: find . -type f -exec grep -qF SOME_STRING {} \; -exec sed 'COMMAND' {} \; The second command will run only if the first one evaluates to true i.e. exit code 0 so sed will process the file in question only if the file contains SOME_STRING. It's easy to see how it works: find . -type f -exec grep -qF SOME_STRING {} ...


1

Just pipe the output of gfind to xargs: gfind /tmp/ -type f \( -name "*.h" -o -name "*.cpp" \) -exec ggrep -l "LARGE_INTEGER" {} + | xargs sed -i '1s/^/#include <stdint.h>\n/' Notice that I've removed the -P option from ggrep, since you're matching a fixed string. However this solution doesn't deal well with filenames containing newlines; a safer ...


1

You need to escape the special characters with a backslash \ in front of the special character. eg. sed 's/\*/t/g' test.txt > test2.txt


4

The following command yields the requested output: cut -d ' ' -f 1,3-10 file1


7

Try this: find /tmp/ -type f -name "*.h" -o -name "*.cpp" \ -exec sed -i '1s/^/#include <stdint.h>\n/' {} + Also, as correctly pointed out to me, the ! -name "*.bak" is superfluous. The -name *foo pattern only matches files ending with foo. Therefore, the *.cpp and *.h already exclude *.bak.


-3

You can do it with: sed -e's/ testhost / testhost testhost1 testhost2 testhost3 /; s/ testhost$/ testhost testhost1 testhost2 testhost3/' /etc/hosts


2

You can do this with sed on a stack... sed '/match$/N s/\n/&INSERT&/3;t $n;N;P;D' That would insert INSERT following every 3rd non-sequential occurrence of match in input. It is the most efficient way I know to do it with sed because it does not attempt to store all lines that occur between different matches, nor does it necessitate ...


-1

AWK solution is a lot easy to read for this kind of tasks, here is just a correction to steviethecat's solution (the ; won't work for awk, need to replace it with a newline): echo -e "DCR\nDCR\nDCR" | awk 'BEGIN {t=0} { print } /DCR/ { t++; if ( t==2) { print "check" } }'


1

Another POSIX answer: paste -d'>\n' /dev/null - - <infile It gets: >Sunshine This is a sunny day. >Darkness A cave is a dark place.


2

POSIXly: sed 's/^/>/;n' < file.in > file.out


2

paste is the tool for this: sed 's/.*[[:blank:]]//' /proc/filesystems | paste -sd,


2

Using awk awk '{printf "%s%s",(NR>1?",":""),$NF;} END{print""}' /proc/filesystems Using sed sed -r 's/^nodev//; s/^[[:blank:]]*//; H;1h;$!d;x; s/\n/,/g' /proc/filesystems How it works s/^nodev// This eliminates nodev from the beginning of any line s/^[[:blank:]]*// This eliminates the leading whitespace from each line. H This appends the ...


1

for i in 799 800 do head -n"$i" >&"$((i&2|1))" done <infile 3>/dev/null The above code will send the first 799 lines of an lseek()able <infile to /dev/null, and the next 800 lines of same to stdout. If you want to prune those 800 lines for sequential uniques, just append |uniq. In that case, you might also do: sed ...


0

Costas' elegant answer in comment sed '800,1600 ! d' file


1

You need the underused sed command r which reads a file: sed -i '/string/{r filename d}' I assume you want to replace the whole line, else replace d by something suitable.


1

bash works well for this: $ cat replace foo/bar\baz the second line $ cat file the replacement string goes >>here<< $ repl=$(<replace) $ str="here" $ while IFS= read -r line; do echo "${line//$str/$repl}" done < file the replacement string goes >>foo/bar\baz the second line<< Awk would work, except that it will ...


0

I got this to work: $ foo='baz' $ echo "foobarbaz" | sed "s/foo/${foo}/" bazbarbaz Taking that one step further, your first line would be something like: $ foo=`cat filename` This assumes you know the filename before you reach the line to be replaced, of course - if you don't, you have to read the line, get the filename, then do the read-and-replace.



Top 50 recent answers are included