Inizio  >  Docs  >  Linux  >  Trucchi veloci  >  Bash  
BashBash

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

stackoverflow.com/questions/8545538/how-do-i-join-pairs-of-consecutive-lines-in-a-large-file-1-million-lines-using

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

 

 
 

To top

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>

 
 

To top

remove new line characters with tr, awk, perl, sed or c/c++

http://linux.dsplabs.com.au/rmnl-remove-new-line-characters-tr-awk-perl-sed-c-cpp-bash-python-xargs-ghc-ghci-haskell-sam-ssam-p65/

 

<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! :D

<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

 
 
 

To top

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

Indietro

Avanti


Appendice C. Una breve introduzione a Sed e Awk

<dl><dt>Sommario</dt><dt>C.1. Sed</dt><dt>C.2. Awk</dt></dl>

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>

print

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
# L'opzione -e indica che la stringa successiva deve essere interpretata come
#+ un'istruzione di editing.
# (se a "sed" viene passata un'unica istruzione, "-e" è facoltativo.)
# Il quoting "forte" ('') protegge i caratteri speciali delle ER, presenti
#+ nell'istruzione, dalla reinterpretazione da parte dello script.
# (Questo riserva solo a sed l'espansione delle ER.)
#
# Agisce sul testo del file $nomefile.

In certi casi, un comando di editing sed non funziona in presenza degli apici singoli.

nomefile=file1.txt
modello=INIZIO

sed "/^$modello/d" "$nomefile" # Funziona come indicato.
# sed '/^$modello/d' "$nomefile" dà risultati imprevisti.
# In questo esempio, il quoting forte (' ... '),
#+ impedisce a "$modello" di espandersi a "INIZIO".

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
# L'opzione -n indica a sed di visualizzare solo quelle righe che verificano
#+ il modello.
# Altrimenti verrebbero visualizzate tutte le righe dell'input.
# L'opzione -e, in questo caso, non sarebbe necessaria perché vi è una sola
#+ istruzione di editing.

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/^  */\
/g

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]/,/^$/{
/^$/d
}

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:

  1. Esempio 33-1

  2. Esempio 33-2

  3. Esempio 15-3

  4. Esempio A-2

  5. Esempio 15-15

  6. Esempio 15-24

  7. Esempio A-12

  8. Esempio A-17

  9. Esempio 15-29

  10. Esempio 10-9

  11. Esempio 15-43

  12. Esempio A-1

  13. Esempio 15-13

  14. Esempio 15-11

  15. Esempio A-10

  16. Esempio 18-12

  17. Esempio 15-16

  18. Esempio A-29

Per una spiegazione più ampia di sed, si controllino i relativi riferimenti in Bibliografia.

Note

[1]

Se non viene specificato alcun indirizzo, sed, in modo predefinito, considera tutte le righe.

 

To top