Ik wil meerdere regels in een bestand invoegen met behulp van shellscript.
Laten we eens kijken naar de inhoud van mijn invoerbestand:
input.txt:
abcd
accd
cdef
line
web
Nu moet ik vier regels invoegen na de regel ‘cdef’ in het bestand input.txt.
Na het invoegen zou mijn bestand als volgt moeten veranderen:
abcd
accd
cdef
line1
line2
line3
line4
line
web
De bovenstaande invoeging zou ik moeten doen met behulp van het shellscript. Kan iemand me helpen?
Antwoord 1, autoriteit 100%
Nog een sed
,
sed '/cdef/r add.txt' input.txt
input.txt:
abcd
accd
cdef
line
web
add.txt:
line1
line2
line3
line4
Testen:
sat:~# sed '/cdef/r add.txt' input.txt
abcd
accd
cdef
line1
line2
line3
line4
line
web
Als u de wijzigingen in het bestand input.txt
wilt toepassen. Gebruik vervolgens -i
met sed
.
sed -i '/cdef/r add.txt' input.txt
Als je een regex als expressie wilt gebruiken, moet je de tag -E
gebruiken met sed
.
sed -E '/RegexPattern/r add.txt' input.txt
Antwoord 2, autoriteit 40%
GNU sed
gebruiken:
sed "/cdef/aline1\nline2\nline3\nline4" input.txt
Als je bent begonnen met:
abcd
accd
cdef
line
web
dit zou het volgende opleveren:
abcd
accd
cdef
line1
line2
line3
line4
line
web
Als u de wijzigingen in het bestand ter plaatse wilt opslaan, zegt u:
sed -i "/cdef/aline1\nline2\nline3\nline4" input.txt
Antwoord 3, autoriteit 25%
sed '/^cdef$/r'<(
echo "line1"
echo "line2"
echo "line3"
echo "line4"
) -i -- input.txt
Antwoord 4, autoriteit 17%
Gebruik awk
:
awk '/cdef/{print $0 RS "line1" RS "line2" RS "line3" RS "line4";next}1' input.txt
Uitleg:
- Je vindt de regel die je wilt invoegen met
/.../
- U drukt de huidige regel af met
print $0
RS
is een ingebouwdeawk
-variabele die standaard is ingesteld opnew-line
.- Je voegt nieuwe regels toe, gescheiden door deze variabele
1
aan het einde resulteert in het afdrukken van elke andere regel. Doornext
te gebruiken voordat het ons in staat stelt om de huidige regel te voorkomen, omdat je het al hebt afgedrukt metprint $0
.
$ awk '/cdef/{print $0 RS "line1" RS "line2" RS "line3" RS "line4";next}1' input.txt
abcd
accd
cdef
line1
line2
line3
line4
line
web
Om wijzigingen in het bestand aan te brengen, kunt u het volgende doen:
awk '...' input.txt > tmp && mv tmp input.txt
Antwoord 5, autoriteit 5%
Hier is een meer algemene oplossing gebaseerd op @rindeal oplossingdie niet werkt op MacOS/BSD (/r
verwacht een bestand):
cat << DOC > input.txt
abc
cdef
line
DOC
$ cat << EOF | sed '/^cdef$/ r /dev/stdin' input.txt
line 1
line 2
EOF
# outputs:
abc
cdef
line 1
line 2
line
Dit kan worden gebruikt om alles op de gegeven positie in het bestand te pipen:
$ date | sed '/^cdef$/ r /dev/stdin' input.txt
# outputs
abc
cdef
Tue Mar 17 10:50:15 CET 2020
line
U kunt ook meerdere opdrachten toevoegen waarmee u de markeringsregel cdef
:
kunt verwijderen
$ date | sed '/^cdef$/ {
r /dev/stdin
d
}' input.txt
# outputs
abc
Tue Mar 17 10:53:53 CET 2020
line
Antwoord 6
Dit antwoord is gemakkelijk te begrijpen
- Kopieer vóór het patroon
- Voeg je regels toe
- Kopieer naar het patroon
-
Origineel bestand vervangen
FILENAME=’app/Providers/AuthServiceProvider.php’
STAP 1 kopiëren tot het patroon
sed '/THEPATTERNYOUARELOOKINGFOR/Q' $FILENAME >>${FILENAME}_temp
STAP 2 voeg je regels toe
cat << 'EOL' >> ${FILENAME}_temp
HERE YOU COPY AND
PASTE MULTIPLE
LINES, ALSO YOU CAN
//WRITE COMMENTS
AND NEW LINES
AND SPECIAL CHARS LIKE $THISONE
EOL
STAP 3 voeg de rest van het bestand toe
grep -A 9999 'THEPATTERNYOUARELOOKINGFOR' $FILENAME >>${FILENAME}_temp
VERVANG origineel bestand
mv ${FILENAME}_temp $FILENAME
als je variabelen nodig hebt, vervang dan in stap 2 ‘EOL’ door EOL
cat << EOL >> ${FILENAME}_temp
this variable will expand: $variable1
EOL
Antwoord 7
Ik moest een paar bestanden sjablonen met minimale tooling en voor mij is het probleem met bovenstaande sed -e '/../r file.txt
dat het het bestand alleen toevoegt nadat het is afgedrukt de rest van de wedstrijd, vervangt het hem niet.
Dit doet het niet (alle overeenkomsten worden vervangen en patroonovereenkomst gaat verder vanaf hetzelfde punt)
#!/bin/bash
TEMPDIR=$(mktemp -d "${TMPDIR:-/tmp/}$(basename $0).XXXXXXXXXXXX")
# remove on exit
trap "rm -rf $TEMPDIR" EXIT
DCTEMPLATE=$TEMPDIR/dctemplate.txt
DCTEMPFILE=$TEMPDIR/dctempfile.txt
# template that will replace
printf "0replacement
1${SHELL} data
2anotherlinenoEOL" > $DCTEMPLATE
# test data
echo -e "xxy \n987 \nxx xx\n yz yxxyy" > $DCTEMPFILE
# print original for debug
echo "---8<--- $DCTEMPFILE"
cat $DCTEMPFILE
echo "---8<--- $DCTEMPLATE"
cat $DCTEMPLATE
echo "---8<---"
# replace 'xx' -> contents of $DCTEMPFILE
perl -e "our \$fname = '${DCTEMPLATE}';" -pe 's/xx/`cat $fname`/eg' ${DCTEMPFILE}
Antwoord 8
Je kunt awk
gebruiken om de uitvoer van een commando in het midden van input.txt
in te voegen.
De in te voegen regels kunnen de uitvoer zijn van een cat otherfile
, ls -l
of 4 regels met een nummer gegenereerd door printf
.
awk 'NR==FNR {a[NR]=$0;next}
{print}
/cdef/ {for (i=1; i <= length(a); i++) { print a[i] }}'
<(printf "%s\n" line{1..4}) input.txt
Antwoord 9
Als je dat met een bash-script wilt doen, is dat handig.
echo $password | echo 'net.ipv4.ping_group_range=0 2147483647' | sudo -S tee -a /etc/sysctl.conf