Index
regexp no-greedy / lazy (stops on first occurence)
You need to make your regular expression non-greedy, because by default, "(.*)" will match all of "file path/level1/level2" xxx some="xxx".
Instead you can make your dot-star non-greedy, which will make it match as few characters as possible:
/location="(.*?)"/
Adding a ? on a quantifier (?, * or +) makes it non-greedy.
tar -ft large_file.tar.gz | grep "the-filename-you-want"
Output:
"full-path/to-the-file/in-the-archive/the-filename-you-want"
tar -xf large_file.tar.gz "full-path/to-the-file/in-the-archive/the-filename-you-want"
in html file, to insert some text around a string between tags
from: <label>Reparto <small>(è possibile la selezione multipla)</small></label>
to: <label><?=$this->translate("Reparto <small>(è possibile la selezione multipla)</small>")?></label><br>
with sed
echo "<label style="pippo">Reparto <small>(è possibile la selezione multipla)</small></label>" |\
> sed -r 's#<label([^>]*)>(.*)</label>#<label\1><?=$this->translate("'\\2'")?></label>#g'
SED find and reuse
se in un file HTML
<p class="bodytext">mia Amica</p>
</td>
<td><p class="bodytext"><a href="javascript:linkTo_UnCryptMailto('nbjmrrrrrfhsfufsjb/dijnjdbcbtfAdijnjdbebhptujop/ju');">segreti@miaAmica.it</a>
</p>
</td>
voglio che questo:
<a href="javascript:linkTo_UnCryptMailto('nbjmddddsfufsjb/dijnjdbcbtfAdijnjdbebhptujop/ju');">segreti@miaAmica.it</a>
diventi:
<a href="mailto:segreti@miaAmica.it">segreti@miaAmica.it</a>
sed 's/\(javascript:linkTo_UnCryptMailto(.*;\).*>\(.*\)<.*/mailto:\2">\2<\/a>/g'
bash rename files removing first part of filename
https://stackoverflow.com/questions/28305134/remove-first-n-character-from-bunch-of-file-names-with-cut
01 Whistle.m4a
01 Wings.m4a
01 Without You.m4a
01 Wrecking Ball.m4a
01 Yeah!.m4a
01 You And I _ You And I.m4a
01 You Are Woman, I Am Man [feat. Io.m4a
01 You Are the Sunshine of My Life.m4a
for pippo in 01* ; do mv "$pippo" "`echo $pippo | cut -c 3-`"; done
mv 01 You're All I Need To Get By.m4a You're All I Need To Get By.m4a
mv 01 You're All the World To Me.m4a You're All the World To Me.m4a
mv 01 You're My Best Friend.m4a You're My Best Friend.m4a
mv 01 You're The Top.m4a You're The Top.m4a
mv 01 You've Lost That Lovin' Feelin'.m4a You've Lost That Lovin' Feelin'.m4a
mv 01 Your Song.m4a Your Song.m4a
bash join pairs of consecutives lines
with TAB as separators
$ seq 10 |paste - -
1 2
3 4
5 6
7 8
9 10
with space as separators
$ seq 10 |paste -d" " - -
1 2
3 4
5 6
7 8
9 10
with , as separators
$ seq 10 |paste -d", " - -
1,2
3,4
5,6
7,8
9,10
Bash script to replace spaces in file names
stackoverflow.com/questions/2709458/bash-script-to-replace-spaces-in-file-names
Use rename (aka prename) which is a Perl script which may be on your system already. Do it in two steps:
find -name "* *" -type d | rename 's/ /_/g' # do the directories first find -name "* *" -type f | rename 's/ /_/g'
Edit:
Based on Jürgen's answer and able to handle multiple layers of files and directories in a single bound using the "Revision 1.5 1998/12/18 16:16:31 rmb1" version of /usr/bin/rename (a Perl script):
find /tmp/ -depth -name "* *" -execdir rename 's/ /_/g' "{}" \;
search (and move) files created in a specific year
#!/bin/bash
OLDIFS=$IFS
IFS='
'
DESTDIR="parts/$1"
mkdir ${DESTDIR}
touch -d "01 january $1 00:00:00" startDate
touch -d "31 december $1 23:59:59" endDate
for FILENAME in `find parts/ -maxdepth 1 -newer ./startDate -and -not -newer ./endDate`
do
mv -v ${FILENAME} ${DESTDIR}
done
IFS=$OLDIFS
sed invert date format from DD-MM-YYYY to YYYY-MM-DD
file dates:
10-02-1984
02-04-1968
09-01-1977
01-09-1975
25-09-1966
08-12-1963
19-04-1990
28-01-1959
18-04-1957
03-11-1984
11-10-1965
22-02-1961
31-08-1962
18-04-1959
22-09-1959
30-06-1987
04-03-1981
30-05-1963
26-06-1984
01-01-1961
05-01-1976
20-02-1971
08-02-1968
16-02-1985
sed 's/\([0-9][0-9]\)\-\([0-9][0-9]\)\-\([0-9][0-9][0-9][0-9]\)/\3\-\2\-\1/g' dates > datesNew
file datesNew:
1984-02-10
1968-04-02
1977-01-09
1975-09-01
1966-09-25
1963-12-08
1990-04-19
1959-01-28
1957-04-18
1984-11-03
1965-10-11
1961-02-22
1962-08-31
1959-04-18
1959-09-22
1987-06-30
1981-03-04
1963-05-30
1984-06-26
1961-01-01
1976-01-05
1971-02-20
1968-02-08
1985-02-16
when execute commands with sudo a new bash envoirment is loaded:
if you try:
sudo env |grep -i proxy
you will get an empty line.
adding this file
/etc/sudoers.d/proxy
containing :
Defaults env_reset
Defaults env_keep += "HTTP_PROXY"
Defaults env_keep += "HTTPS_PROXY"
Defaults env_keep += "http_proxy"
Defaults env_keep += "https_proxy"
now with:
sudo env |grep -i proxy
you'll have this output:
http_proxy=http://192.168.2.3:8080/
https_proxy=http://192.168.2.3:8080/
HTTPS_PROXY=http://192.168.2.3:8080/
HTTP_PROXY=http://192.168.2.3:8080/
so the env variables have passed to the sudo env
grep con OR
egrep -i '(text1)|(text2)' filename
check Garageband HW platform
#!/bin/bash
OLDIFS=$IFS
IFS='
'
for garages in `find . -name "*.band"`
do
echo $garages: `egrep -i '(ios)|(x86_64)' $garages/projectData |cut -d \> -f 2|cut -d \< -f 1`
done
IFS=$OLDIFS
convert GarageBand from Ipad to mac and back
Ipad to mac
#!/bin/bash
OLDIFS=$IFS
IFS='
'
for DIR in `ls -1 *.band|grep :|cut -d \: -f1`
do echo ${DIR}
cd ${DIR}
sed -i.bak 's/iPad3,1/x86_64/' projectData
sed -i.bak 's/ios/macos/' projectData
sed -i.bak 's/ios/macos/' Output/metadata.plist
sed -i.bak 's/iPad3,1/x86_64/' Output/metadata.plist
cd ..
done
IFS=$OLDIFS
mac to Ipad
#!/bin/bash
OLDIFS=$IFS
IFS='
'
for DIR in `ls -1 *.band|grep :|cut -d \: -f1`
do echo ${DIR}
cd ${DIR}
sed -i.bak 's/x86_64/iPad3,1/' projectData
sed -i.bak 's/macos/ios/' projectData
sed -i.bak 's/macos/ios/' Output//metadata.plist
sed -i.bak 's/x86_64/iPad3,1/' Output//metadata.plist
cd ..
done
IFS=$OLDIFS
Rename Mp3 file from id3 Tags
for pippo in `ls -1`; do eyeD3 --rename="../al3ssia/%n - %t" $pippo; done
OR
#!/bin/bash
TITLE="`id3tool "$1" | grep '^Song Title:' | awk '{ for (i=3;i<=NF;i++) { printf $i; printf " " } }'`"
ARTIST="`id3tool "$1" | grep '^Artist:' | awk '{ for (i=2;i<=NF;i++) { printf $i; printf " " } }'`"
ALBUM="`id3tool "$1" | grep '^Album:' | awk '{ for (i=2;i<=NF;i++) { printf $i; printf " " } }'`"
YEAR="`id3tool "$1" | grep '^Year:' | awk '{ for (i=2;i<=NF;i++) { printf $i; printf " " } }'`"
TRACKNUM="`id3tool "$1" | grep '^Year:' | awk '{ print $2 }'`"
OR
#!/bin/bash
TITLE="`id3info "$1" | grep '^=== TIT2' | sed -e 's/.*: //g'`"
ARTIST="`id3info "$1" | grep '^=== TPE1' | sed -e 's/.*: //g'`"
ALBUM="`id3info "$1" | grep '^=== TALB' | sed -e 's/.*: //g'`"
YEAR="`id3info "$1" | grep '^=== TYER' | sed -e 's/.*: //g'`"
TRACKNUM="`id3info "$1" | grep '=== TRCK' | sed -e 's/.*: //g'`"
echo "$ARTIST $TITLE $ALBUM $YEAR $TRACKNUM"
mv $1 "$ARTIST - $ALBUM - $TRACKNUM - $TITLE.mp3"
move files from dir taking dirname (name with spaces) (copia 1)
O=$IFS
IFS=$'\n'
for pippo in `ls -1 -d */|cut -d / -f 1`
do
mv -v "$pippo"/Game.cdz "$pippo".cdz
rm -rf "$pippo"/
done
IFS=$O
Remove or replace newlines using sed,awk,tr - BASH
http://unstableme.blogspot.com/2008/05/remove-or-replace-newlines-using.html
$ cat week.txt
Su
Mo
Tu
We
Th
Fr
Sa
Output Required:
- a) Remove the newlines. i.e. required output:
SuMoTuWeThFrSa
- b) Replace the newlines with "|", i.e.
Su|Mo|Tu|We|Th|Fr|Sa
Remove/Replace newlines with sed
a)
$ sed -e :a -e '$!N;s/\n//;ta' week.txt
SuMoTuWeThFrSa
b)
$ sed -e :a -e '$!N;s/\n/|/;ta' week.txt
Su|Mo|Tu|We|Th|Fr|Sa
One more way of doing. But not suitable for files with large number of records, as you see the number of N's is just 1 less than number of lines in the file.
a)
$ sed 'N;N;N;N;N;N;s/\n//g' week.txt
SuMoTuWeThFrSa
b)
$ sed 'N;N;N;N;N;N;s/\n/|/g' week.txt
Su|Mo|Tu|We|Th|Fr|Sa
Remove/Replace newlines with awk
a)
$ awk '{printf "%s",$0} END {print ""}' week.txt
SuMoTuWeThFrSa
b)
$ awk '{printf "%s|",$0} END {print ""}' week.txt
Su|Mo|Tu|We|Th|Fr|Sa|
So we need to remove the last "|" in the above output.
$ awk '{printf "%s|",$0} END {print ""}' week.txt | awk '{sub(/\|$/,"");print}'
Su|Mo|Tu|We|Th|Fr|Sa
Remove/Replace newlines with tr
a)
$ tr -d '\n' < week.txt
SuMoTuWeThFrSa
b)
$ tr '\n' '|' < week.txt
Su|Mo|Tu|We|Th|Fr|Sa|
Similarly we need to remove the last "|" from the above output:
$ tr '\n' '|' < week.txt | sed 's/|$//'
Su|Mo|Tu|We|Th|Fr|Sa
One more:<dl class="avatar-comment-indent" id="comments-block"><dd class="comment-body" id="Blog1_cmt-2271710975389617176">
$ jot -c 10 A
A
B
C
D
E
F
G
H
I
J
$ jot -c 10 A | paste -sd,
A,B,C,D,E,F,G,H,I,J
Moreover,
$ jot -c 10 A | tr '\n' ',' | sed -e "s/[A-Z]*/'&'/g" -e "s/,''/\n/g"
'A','B','C','D','E','F','G','H','I','J'
$ jot -c 10 A | awk -v x="'" '{ s=s sprintf(x "%s" x ",", $0) } END { sub(",$", "", s); print(s) }'
'A','B','C','D','E','F','G','H','I','J'
</dd></dl>
remove new line characters with tr, awk, perl, sed or c/c++
<code>rmnl</code> — remove new line characters with tr, awk, perl, sed or c/c++
How to remove new lines from files or pipe streams under Linux? This post contains simple examples that show how to use common Linux shell tools such as <code>tr</code>, <code>awk/gawk</code>, <code>perl</code>, <code>sed</code> and many others to delete new line characters. C and C++ source codes are also provided. They can be compiled into a binary tool that removes new lines. To get started, here is an example text file: days.txt. Lets have a look at its content by running the following command from shell.
cat days.txt ©2007-2008 dsplabs.com.au
The output is shown below.
Mon
Tue
Wed
Thu
Fri
Sat
Sun
If the new lines were removed from days.txt then its content would look like this:
MonTueWedThuFriSatSun
If instead of simply removing the new line characters they were replaced with spaces then the output would look as follows.
Mon Tue Wed Thu Fri Sat Sun
Below are simple examples of two types: one to remove new lines and the other to replace them with spaces. The outputs of these examples are as shown above.
<code>tr</code> — remove new line characters with tr
Either of the following commands can be used to delete new lines using the <code>tr</code> utility.
tr -d '\n' < days.txt
cat days.txt | tr -d '\n'
While the new line characters can be replaced with spaces using the <code>tr</code> program as follows.
tr '\n' ' ' < days.txt
cat days.txt | tr '\n' ' '
<code>awk</code> — remove new line characters with awk or gawk
Either of the following commands can be used to delete new lines using <code>awk</code> or <code>gawk</code>.
awk '{ printf "%s", $0 }' days.txt
cat days.txt | awk '{ printf "%s", $0 }'
While the new line characters can be replaced with spaces using either of the following commands.
awk '{ printf "%s ", $0 }' days.txt
cat days.txt | awk '{ printf "%s ", $0 }'
Please be careful when using <code>printf</code>'s: never pass any unvalidated inputs to <code>printf</code> as a format string as it is a security risk. That is, use: <code>{ printf "%s ", $0 }</code> but not: <code>{ printf $0 }</code>.
<code>perl</code> — remove new line characters with perl
Either of the following commands can be used to delete new lines using <code>perl</code>.
perl -e 'while (<>) { chomp; print; }; exit;' days.txt
cat days.txt | perl -e 'while (<>) { chomp; print; }; exit;'
While the new line characters can be replaced with spaces using either of the following commands.
perl -e 'while (<>) { chomp; print; print " "; }; exit;' days.txt
cat days.txt | perl -e 'while (<>) { chomp; print; print " "; }; exit;'
Here are some more <code>perl</code> examples:
perl -p -e 's/\s+$/ /g' days.txt
cat days.txt | perl -p -e 's/\s+$/ /g'
The above regex approach is actually much simpler and neater!
<code>sed</code> — remove new line characters with sed
You could also use <code>sed</code> to remove new lines. The solution using <code>sed</code> is not very readable but it works. Use either of the following commands.
sed ':a;N;$!ba;s/\n//g' days.txt
cat days.txt | sed ':a;N;$!ba;s/\n//g'
Or, to replace the new line characters with spaces use either of the following commands.
sed ':a;N;$!ba;s/\n/ /g' days.txt
cat days.txt | sed ':a;N;$!ba;s/\n/ /g'
James of crypto.dsplabs.com.au suggested this, easier to read, <code>sed</code> solution on the Linux Blog Forums:
sed '{:q;N;s/\n//g;t q}' days.txt
<code>C</code> or <code>C++</code> — remove new line characters with a C or C++ based binary
If you fancy none of the above approaches then create your own binary tool for this task using for example C or C++. Here is an example C source code: rmnl.c also courtesy of James.
#include <stdio.h> int main(int argc, char *argv[]) { char k; while((k = getchar()) != EOF) if(k != 0x0D && k != 0x0A) putchar(k); // else putchar(' '); // replace newlines with spaces putchar(0x0A); return 0; }
While my attempt at writing a new line removal tool in C++, rmnl.cpp, is listed below.
#include <iostream> using namespace std; int main() { string line; while( getline(cin, line) && !cin.eof() ) cout << line; // delete newlines // while( getline(cin, line) && !cin.eof() ) cout << line << ' '; // replace n with spaces cout << endl; return 0; }
Another way in C++ is to use stream iterators like so:
#include <iostream> #include <iterator> int main () { std::remove_copy( std::istream_iterator<char>( std::cin ), std::istream_iterator<char>(), std::ostream_iterator<char>( std::cout ), '\n' ); }
To compile the above sources with GNU gcc or g++ compiler use the following commands, respectively.
gcc rmnl.c -o rmnl g++ rmnl.cpp -o rmnl
Either of the following commands can be used to run the newly created <code>rmnl</code> binary assuming that <code>rmnl</code> is in your path.
cat days.txt | rmnl rmnl < days.txt
If <code>rmnl</code> binary in not in your path variable, but it is in your current directory, then replace <code>rmnl</code> above with <code>./rmnl</code> like so:
cat days.txt | ./rmnl ./rmnl < days.txt
Here is the compiled binary: <code>rmnl</code> and some information about it:
$>file rmnl rmnl: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped $>ldd rmnl linux-gate.so.1 => (0x0041d000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00b21000) libm.so.6 => /lib/libm.so.6 (0x0086c000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x009ec000) libc.so.6 => /lib/libc.so.6 (0x0072a000) /lib/ld-linux.so.2 (0x0070d000)
Other approaches for removal of new line characters
The following are thanks to reddit.com readers.
Replacing new lines with spaces using <code>xargs</code>:
xargs echo < days.txt cat days.txt | xargs echo cat days.txt | xargs echo -n
Removing new lines using Haskell, f.e. with the Glasgow Haskell Compiler, <code>ghci</code>:
cat days.txt | ghci -e "interact (concat . lines)"
Removing new lines or substituting them with spaces using sam
text editor:
printf ", x/.*/nq" | sam -d days.txt 2>/dev/null (echo ', x/\n/ c/ /'; echo ', p'; echo q) | sam -d days.txt 2>/dev/null
Or its stream version ssam
:
ssam -n ', x/.*/ p' < days.txt 2>/dev/null ssam ', x/\n/ c/ /' < days.txt 2>/dev/null
Another approach is to use GNU Bash like so:
while read; do echo -n "$REPLY "; done < days.txt
Or even simpler:
echo -n `cat days.txt`
Or, Python like this:
python -c 'import sys; print sys.stdin.read().replace("\n", " ")' < days.txt
Sed
http://sed.sourceforge.net/sed1line.txt
http://www.squadrainformatica.com/it/blog/roadmap_sed
-------------------------------------------------------------------------
ESEMPI PER SED (Unix stream editor) Apr. 26, 2004
scritto da Eric Pement - pemente[at]northpark[dot]edu version 5.4
La ultima versione di questo file si trova normalmente qui:
http://sed.sourceforge.net/sed1line.txt
http://www.student.northpark.edu/pemente/sed/sed1line.txt
Questo file è anche disponibile in Portoghese qui:
http://www.lrv.ufsc.br/wmaker/sed_ptBR.html
Questo file è anche disponibile in Italiano qui:
RIGHE VUOTE:
# riga vuota in un file
sed G
# riga vuota in un file che ha già delle linee vuote. Il file di output
# non dovrebbe contenere più di una sola riga vuota tra due righe di testo
sed '/^$/d;G'
# doppia riga vuota in un file
sed 'G;G'
# elimina le righe vuote (assume che le righe dispari siano sempre vuote)
sed 'n;d'
# inserisce una riga vuota sopra ogni riga che verifica la "regex"
sed '/regex/{x;p;x;}'
# inserisce una riga vuota sotto ogni riga che verifica la "regex"
sed '/regex/G'
# inserisce una riga vuota sopra e sotto ogni riga che verifica la "regex"
sed '/regex/{x;p;x;G;}'
NUMERAZIONE:
# numera ogni riga presente in un file (con allineamento a sinistra). Usa un <tab> (leggi
# la nota su "\t" in fondo a questo file) al posto di uno spazio per preservare i margini
sed = filename | sed 'N;s/\n/\t/'
# numera ogni riga presente in un file (con allineamento a sinistra e a destra)
sed = filename | sed 'N; s/^/ /; s/ *\(.\{6,\}\)\n/\1 /'
# numera ogni riga presente in un file, ma numera solo le righe non vuote
sed '/./=' filename | sed '/./N; s/\n/ /'
# conta le righe (emulando "wc -l")
sed -n '$='
CONVERSIONE E SOSTITUZIONE DI TESTO:
# IN AMBIENTE UNIX: converte il carattere "a capo" dal formato DOS a quello UNIX
sed 's/.$//' # assume che tutte le righe finiscano con CR/LF
sed 's/^M$//' # in bash/tcsh, premi Ctrl-V poi Ctrl-M
sed 's/\x0D$//' # gsed 3.02.80, ma lo script sopra è piu facile
# IN AMBIENTE UNIX: converte il carattere "a capo" (LF) dal formato unix al formato DOS
sed "s/$/`echo -e \\\r`/" # linea di comando per ksh
sed 's/$'"/`echo \\\r`/" # linea di comando per bash
sed "s/$/`echo \\\r`/" # linea di comando per zsh
sed 's/$/\r/' # gsed 3.02.80
# IN AMBIENTE DOS: converte il carattere "a capo" (LF) dal formato unix al formato DOS
sed "s/$//" # metodo 1
sed -n p # metodo 2
# IN AMBIENTE UNIX: converte il carattere "a capo" (CR/LF) dal formato DOS a quello UNIX
# Può essere fatto solo con UnxUtils sed, versione 4.0.7 or superiore.
# Non può essere fatto con altre versioni dos di sed. Usa piuttosto "tr"
sed "s/\r//" infile >outfile # UnxUtils sed v4.0.7 o superiore
tr -d \r <infile >outfile # GNU tr versione 1.22 o superiore
# elimina il carattere spazio (spazi, tabs) dall'inizio di ogni riga
# allinea il testo a sinistra
sed 's/^[ \t]*//' # leggi la nota su '\t' alla fine del file
# elimina il carattere spazio (spazi, tabs) dalla fine di ogni riga
sed 's/[ \t]*$//' # leggi la nota su '\t' alla fine del file
# elimina sia qui spazi iniziali che quelli finali da ogni riga
sed 's/^[ \t]*//;s/[ \t]*$//'
# inserisce 5 spazi bianchi all'inizio di ogni riga (fa un'indentazione della pagina)
sed 's/^/ /'
# allinea il testo ad una larghezza di 79 colonne
sed -e :a -e 's/^.\{1,78\}$/ &/;ta' # fissa il 78esimo più uno spazio
# centra il testo al centro della 79 colonne. Nel metodo 1
# gli spazi all'inizio della riga sono significativi, e quelli finali
# sono appesi alla fine della riga. Nel secondo metodo, gli spazi
# all'inizio della riga non sono considerati ai fini dell'allineamento, e
# non vengono aggiunti gli spazi al termine della riga.
sed -e :a -e 's/^.\{1,77\}$/ & /;ta' # metodo 1
sed -e :a -e 's/^.\{1,77\}$/ &/;ta' -e 's/\( *\)\1/\1/' # metodo 2
# sostituisce (trova e sostituisce) "foo" con "bar" per ogni riga
sed 's/foo/bar/' # sostituisce solo la prima istanza trovata nella riga
sed 's/foo/bar/4' # sostituisce solo le prime 4 istanze trovate nella riga
sed 's/foo/bar/g' # sostituisce tutte le istanze trovate nella riga
sed 's/\(.*\)foo\(.*foo\)/\1bar\2/' # sostituisce la penultima istanza
sed 's/\(.*\)foo/\1bar/' # sostituisce l'ultima istanza
# sostituisce "foo" con "bar" solo nelle righe che contengono "baz"
sed '/baz/s/foo/bar/g'
# sostituisce "foo" con "bar" ad eccezione delle righe che contengono "baz"
sed '/baz/!s/foo/bar/g'
# sostituisce "scarlet" o "ruby" o "puce" in "red"
sed 's/scarlet/red/g;s/ruby/red/g;s/puce/red/g' # la maggior parte dei sed
gsed 's/scarlet\|ruby\|puce/red/g' # solo GNU sed
# linee in ordine inverso (emula "tac")
# un bug/caratteristica in HHsed v1.5 causa la non rimozione delle linee vuote
sed '1!G;h;$!d' # metodo 1
sed -n '1!G;h;$p' # metodo 2
# inverte l'ordine dei caratteri in una riga (emula "rev")
sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'
# accoda le righe pari a quelle dispari separandole con uno spazio (simile a "paste")
sed '$!N;s/\n/ /'
# se una riga finisce con backslash (\), appendile la linea successiva
sed -e :a -e '/\\$/N; s/\\\n//; ta'
# se una riga inizia con il segno uguale (=), appendila alla riga precedente
# e rimpiazia "=" con un singolo spazio
sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'
# aggiunge la virgola (,) alle stringhe numeriche, modificando "1234567" in "1,234,567"
gsed ':a;s/\B[0-9]\{3\}\>/,&/;ta' # GNU sed
sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta' # altri sed
# aggiunge la virgola ai numeri con il punto decimale e con segno meno (GNU sed)
gsed ':a;s/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g;ta'
# aggiunge una riga vuota ogni 5 righe (dopo le righe 5, 10, 15, 20, etc.)
gsed '0~5G' # solo GNU sed
sed 'n;n;n;n;G;' # altri sed
SELECTIVE PRINTING OF CERTAIN LINES:
# stampa le prime 10 righe di un file (emula "head")
sed 10q
# stampa la prima riga di un file (emula "head -1")
sed q
# stampa le ultime 10 righe di un file (emula "tail")
sed -e :a -e '$q;N;11,$D;ba'
# stampa le ultime 2 righe di un file (emula "tail -2")
sed '$!N;$!D'
# stampa l'ultima riga di un file (emula "tail -1")
sed '$!d' # metodo 1
sed -n '$p' # metodo 2
# stampa solo le linee che verificano la espressione regolare (emula "grep")
sed -n '/regexp/p' # metodo 1
sed '/regexp/!d' # metodo 2
# stampa solo le linee che NON verificano la espressione regolare (emula "grep -v")
sed -n '/regexp/!p' # metodo 1, corrisponde a sopra
sed '/regexp/d' # metodo 2, sintassi più semplice
# stampa la riga immediatamente precedente alla linea che verifica
# la espressione regolare
sed -n '/regexp/{g;1!p;};h'
# stampa la riga immediatamente successiva alla linea che verifica
# la espressione regolare
sed -n '/regexp/{n;p;}'
# stampa la riga immediatamente precedente e quella successiva alla linea che verifica
# la espressione regolare (simile a "grep -A1 -B1")
sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e h
# cerca le righe contenenti AAA e BBB e CCC (in ogni ordine)
sed '/AAA/!d; /BBB/!d; /CCC/!d'
# cerca le righe contenenti AAA e BBB e CCC (nell' ordine)
sed '/AAA.*BBB.*CCC/!d'
# cerca le righe contenenti AAA o BBB o CCC (emula "egrep")
sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d # most seds
gsed '/AAA\|BBB\|CCC/!d' # GNU sed only
# stampa il paragrafo se contiene AAA (le righe vuote demarcano la separazione tra i paragrafi)
# HHsed v1.5 deve avere una 'G;' dopo 'x;' nei prossimi 3 comandi.
sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;'
# stampa il paragrafo se contiene AAA e BBB e CCC (in ogni ordine)
sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;/BBB/!d;/CCC/!d'
# stampa il paragrafo se contiene AAA o BBB o CCC
sed -e '/./{H;$!d;}' -e 'x;/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d
gsed '/./{H;$!d;};x;/AAA\|BBB\|CCC/b;d' # GNU sed only
# stampa solo le righe lunghe almeno 65 caratteri
sed -n '/^.\{65\}/p'
# stampa solo le righe più corte di 65 caratteri
sed -n '/^.\{65\}/!p' # metodo 1, corresponds to above
sed '/^.\{65\}/d' # metodo 2, simpler syntax
# stampa la sezione di file tra la linea che verifica l'espressione regolare e la fine del file
sed -n '/regexp/,$p'
Sed / Awk
Notazione | Effetto |
---|---|
<code class="OPTION">8d</code> | Cancella l'ottava riga dell'input. |
<code class="OPTION">/^$/d</code> | Cancella tutte le righe vuote. |
<code class="OPTION">1,/^$/d</code> | Cancella dall'inizio dell'input fino alla prima riga vuota compresa. |
<code class="OPTION">/Jones/p</code> | Visualizza solo le righe in cui è presente "Jones" (con l'opzione -n). |
<code class="OPTION">s/Windows/Linux/</code> | Sostituisce con "Linux" la prima occorrenza di "Windows" trovata in ogni riga dell'input. |
<code class="OPTION">s/BSOD/stabilità/g</code> | Sostituisce con "stabilità" tutte le occorrenze di "BSOD" trovate in ogni riga dell'input. |
<code class="OPTION">s/ *$//</code> | Cancella tutti gli spazi che si trovano alla fine di ogni riga. |
s/^ *// | Cancella tutti gli spazi che si trovano all'inizio di ogni riga. |
<code class="OPTION">s/00*/0/g</code> | Riduce ogni sequenza consecutiva di zeri ad un unico zero. |
<code class="OPTION">/GUI/d</code> | Cancella tutte le righe in cui è presente "GUI". |
<code class="OPTION">s/GUI//g</code> | Cancella tutte le occorrenze di "GUI", lasciando inalterata la parte restante di ciascuna riga. |
http://www.pluto.it/files/ildp/guide/abs/sedawk.html
Guida avanzata di scripting Bash: Un'approfondita esplorazione dell'arte dello scripting di shell | ||
---|---|---|
Appendice C. Una breve introduzione a Sed e Awk
Questa è una brevissima introduzione alle utility di elaborazione di testo sed e awk. Qui vengono trattati solamente alcuni comandi di base, ma che saranno sufficienti per comprendere i semplici costrutti sed e awk presenti negli script di shell.
sed: editor non interattivo di file di testo
awk: linguaggio per l'elaborazione di modelli orientato ai campi, con una sintassi simile a quella del C
Nonostante le loro differenze, le due utility condividono una sintassi d'invocazione simile, entrambe fanno uso delle Espressioni Regolari, entrambe leggono l'input, in modo predefinito, dallo <tt>stdin</tt> ed entrambe inviano i risultati allo <tt>stdout</tt>. Sono strumenti UNIX ben collaudati e funzionano bene insieme. L'output dell'una può essere collegato, per mezzo di una pipe, all'altra e le loro capacità combinate danno agli script di shell parte della potenza di Perl.
Un'importante differenza tra le due utility è che mentre gli script di shell possono passare facilmente degli argomenti a sed, è più complicato fare la stessa cosa con awk (vedi Esempio 33-5 e Esempio 9-24). |
C.1. Sed
Sed è un editor di riga non interattivo. Riceve un testo come input, o dallo <tt>stdin</tt> o da un file, esegue alcune operazioni sulle righe specificate, una alla volta, quindi invia il risultato allo <tt>stdout</tt> o in un file. Negli script di shell, sed è, di solito, una delle molte componenti di una pipe.
Sed determina le righe dell'input, su cui deve operare, tramite un indirizzo che gli è stato passato. [1] Questo indirizzo può essere rappresentato sia da un numero di riga sia da una verifica d'occorrenza. Ad esempio, <tt>3d</tt> indica a sed di cancellare la terza riga dell'input, mentre <tt>/windows/d</tt> segnala a sed che si vogliono cancellare tutte le righe dell'input contenenti l'occorrenza "windows".
Di tutte le operazioni a disposizione di sed, vengono focalizzate, in primo luogo, le tre più comunemente usate. Esse sono print (visualizza allo <tt>stdout</tt>), delete (cancella) e substitute (sostituisce).
Tabella C-1. Operatori sed di base
Operatore | Nome | Effetto |
---|---|---|
<code class="OPTION">[indirizzo]/p</code> | Visualizza [l'indirizzo specificato] | |
<code class="OPTION">[indirizzo]/d</code> | delete | Cancella [l'indirizzo specificato] |
<code class="OPTION">s/modello1/modello2/</code> | substitute | Sostituisce in ogni riga la prima occorrenza della stringa modello1 con la stringa modello2 |
<code class="OPTION">[indirizzo]/s/modello1/modello2/</code> | substitute | Sostituisce, in tutte le righe specificate in <tt>indirizzo</tt>, la prima occorrenza della stringa modello1 con la stringa modello2 |
<code class="OPTION">[indirizzo]/y/modello1/modello2/</code> | transform | sostituisce tutti i caratteri della stringa modello1 con i corrispondenti caratteri della stringa modello2, in tutte le righe specificate da <tt>indirizzo</tt> (equivalente di tr) |
<code class="OPTION">g</code> | global | Agisce su tutte le verifiche d'occorrenza di ogni riga di input controllata |
Se l'operatore <code class="OPTION">g</code> (global) non è accodato al comando substitute, la sostituzione agisce solo sulla prima verifica d'occorrenza di ogni riga. |
Sia da riga di comando che in uno script di shell, un'operazione sed può richiedere il quoting e alcune opzioni.
sed -e '/^$/d' $nomefile |
In certi casi, un comando di editing sed non funziona in presenza degli apici singoli.
nomefile=file1.txt |
Sed utilizza l'opzione <code class="OPTION">-e</code> per indicare che la stringa che segue è un'istruzione, o una serie di istruzioni. Se la stringa contiene una singola istruzione, allora questa opzione può essere omessa. |
sed -n '/xzy/p' $nomefile |
Tabella C-2. Esempi di operatori sed
Notazione | Effetto |
---|---|
<code class="OPTION">8d</code> | Cancella l'ottava riga dell'input. |
<code class="OPTION">/^$/d</code> | Cancella tutte le righe vuote. |
<code class="OPTION">1,/^$/d</code> | Cancella dall'inizio dell'input fino alla prima riga vuota compresa. |
<code class="OPTION">/Jones/p</code> | Visualizza solo le righe in cui è presente "Jones" (con l'opzione -n). |
<code class="OPTION">s/Windows/Linux/</code> | Sostituisce con "Linux" la prima occorrenza di "Windows" trovata in ogni riga dell'input. |
<code class="OPTION">s/BSOD/stabilità/g</code> | Sostituisce con "stabilità" tutte le occorrenze di "BSOD" trovate in ogni riga dell'input. |
<code class="OPTION">s/ *$//</code> | Cancella tutti gli spazi che si trovano alla fine di ogni riga. |
<code class="OPTION">s/00*/0/g</code> | Riduce ogni sequenza consecutiva di zeri ad un unico zero. |
<code class="OPTION">/GUI/d</code> | Cancella tutte le righe in cui è presente "GUI". |
<code class="OPTION">s/GUI//g</code> | Cancella tutte le occorrenze di "GUI", lasciando inalterata la parte restante di ciascuna riga. |
Sostituire una stringa con un'altra di lunghezza zero (nulla) equivale a cancellare quella stringa nella riga di input. Questo lascia intatta la parte restante della riga. L'espressione <kbd class="USERINPUT">s/GUI//</kbd> applicata alla riga
<kbd class="USERINPUT">Le parti più importanti di ogni applicazione sono le sue GUI e gli effetti sonori</kbd> |
dà come risultato
<samp class="COMPUTEROUTPUT">Le parti più importanti di ogni applicazione sono le sue e gli effetti sonori</samp> |
La barra inversa costringe il comando di sostituzione sed a continuare sulla riga successiva. L'effetto è quello di usare il carattere di a capo alla fine della prima riga come stringa di sostituzione.
s/^ */\ |
In questo modo, tutti gli spazi che si trovano all'inizio della riga vengono sostituiti con un carattere di a capo. Il risultato finale è la sostituzione di tutte le indentazioni dei paragrafi con righe vuote poste tra gli stessi paragrafi.
Un indirizzo seguito da una, o più, operazioni può richiedere l'impiego della parentesi graffa aperta e chiusa, con un uso appropriato dei caratteri di a capo.
/[0-9A-Za-z]/,/^$/{ |
Questo cancella solo la prima di ogni serie di righe vuote. Potrebbe essere utile per effettuare la spaziatura singola di un file di testo mantenendo, però, la/e riga/he vuota/e tra i paragrafi.
L'usuale delimitatore usato da sed è la /. Tuttavia, sed consente anche altri delimitatori, come %. Questo torna utile quando la / è contenuta nella stringa di sostituzione, come nei percorsi dei file. Vedi Esempio 10-9 e Esempio 15-29. |
La via più rapida per effettuare una spaziatura doppia di un file di testo è <kbd class="USERINPUT">sed G nomefile</kbd>. |
Per esempi che illustrano l'uso di sed negli script di shell, vedi:
Per una spiegazione più ampia di sed, si controllino i relativi riferimenti in Bibliografia.
Note
Se non viene specificato alcun indirizzo, sed, in modo predefinito, considera tutte le righe. |