Bir dize içeren tüm satırı Sed kullanarak değiştir


319

Benim gibi belirli bir çizgi olan bir metin dosyası var

sometext sometext sometext TEXT_TO_BE_REPLACED sometext sometext sometext

Yukarıdaki tüm satırı değiştirmem gerekiyor

This line is removed by the admin.

Arama anahtar kelimesi: TEXT_TO_BE_REPLACED

Bunun için bir kabuk komut dosyası yazmam gerekiyor. Bunu kullanarak nasıl başarabilirim sed?


@Scharron sed -rne 's / (TEXT_TO_BE_REPLACED) \ s + \ w + / \ 1 yyy / xxx' komutunu denedim. Ancak, herhangi bir yyy varsa bu sadece dizede yyy'yi xxx ile değiştirir. Benim durumumda metin sabit değil ... sahip olduğum tek şey TEXT_TO_BE_REPLACED.
Rahul

bu geçerli bir sed ifadesi değil. Sed ile istediğinizden emin misiniz? Normal ifadelere sahip herhangi bir programlama dili sizin için bir değişiklik yapabilir (bir alt işlev arayın). Bu kendiniz sed anlamaktan daha kolay olurdu
Scharron

@Scharron Peki, onun kabuk komut dosyası ile yapılması bu yüzden sed benim en iyi bahis olduğunu tahmin ediyorum.
Rahul

Yanıtlar:


483

Tüm satırı değiştirmek için change komutunu -ive değişiklikleri yerinde yapmak için bayrağı kullanabilirsiniz. Örneğin, GNU sed kullanarak:

sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo

4
C \ 'dan önce bir boşluğa ihtiyacınız olduğunu unutmayın. Bunu eklemek için yeni düzenledim.
Marcus Downing

27
@MarcusDowning GNU gelmez sed değil alana ihtiyaç; başlangıçta yayınlanan gibi iyi çalışıyor. Özel sed'iniz alanı gerektiriyorsa, elbette hangi sed'in uyumsuz olduğuna dikkat edin ve gerekli çağrıyı yorum olarak ekleyin. Ancak, kabul edilen bir yanıtta lütfen çalışma kodunu değiştirmeyin.
Todd A. Jacobs

7
"This ..." metni yerine bir değişkeni nasıl kullanabilirim? $ Değişkeniyle değiştirirsem, içeriğini değil değişken adını yazdırır.
Steven

18
c\ Doğrudan bir değişken tarafından takip edildiğinde sorun var : …c\$VAR…Ters eğik çizgi dolardan kaçacak. Bu durumda I (bash / Ubuntu 15.10 sed) yazmak zorunda…c\\$VAR…
Oca

6
mac kullanımı sed -i '' '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo:; (ilk parametre boş olduğunda dosyada düzenler, aksi takdirde bir yedek oluşturur)
AndreDurao

152

.*Tüm satırı değiştirmek için önce ve sonra wildards ( ) kullanmanız gerekir :

sed 's/.*TEXT_TO_BE_REPLACED.*/This line is removed by the admin./'

Teşekkür ederim, benim çalışmam var: sed 's /.* <ifade>. * / <İfade> SE_LABEL = ABC <ifade> / g' MYR2.xml> test.txt
Nasri Najib

9
Aşağıdaki gibi -i ve -e bayraklarını kullanmam haricinde Mac OS X Yosemite üzerinde çalışıyor:sed -i -e "s/.*search_string.*/Replacement_line/' file_being_searched.txt
Kent Bull

1
@KentJohnson Bence emrinizde tırnak işaretleri yanlış.
HashHazard

@Marnett haklısın, orada iki çift tırnak olmalı.
Kent Bull

2
Tam bilgi için. Yerinde yapmak için -iseçenek ekleyebilirsiniz
Temak

20

Kabul edilen cevap benim için birkaç nedenden dolayı işe yaramadı:

  • sed versiyonum -isıfır uzunluklu bir uzatma ile sevmiyor
  • c\komutun sözdizimi garip ve işe yaramadım
  • Sorunlarımdan bazılarının kaçışsız eğik çizgilerden geldiğini fark etmedim

İşte size, çoğu durumda işe yarayacağını düşündüğüm çözüm:

function escape_slashes {
    sed 's/\//\\\//g' 
}

function change_line {
    local OLD_LINE_PATTERN=$1; shift
    local NEW_LINE=$1; shift
    local FILE=$1

    local NEW=$(echo "${NEW_LINE}" | escape_slashes)
    sed -i .bak '/'"${OLD_LINE_PATTERN}"'/s/.*/'"${NEW}"'/' "${FILE}"
    mv "${FILE}.bak" /tmp/
}

Yani sorunu çözmek için örnek kullanım ortaya çıktı:

change_line "TEXT_TO_BE_REPLACED" "This line is removed by the admin." yourFile

18

Yukarıdaki cevap:

sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo

Değiştirme dizesi / satırı bir değişken değilse iyi çalışır.

Sorun şu ki Redhat 5'te kaçış \sonrası . Bir çift de işe yaramadı (en azından Redhat 5'te).c$\\

Vuruş ve deneme yoluyla , yedek dizeniz / satırınız yalnızca tek bir satırsa , \sonrasının cgereksiz olduğunu keşfettim . Ben kullanmadım Yani \sonra c, tek bir yedek hat olarak bir değişken kullanılır ve sevinç oldu.

Kod şöyle görünecektir:

sed -i "/TEXT_TO_BE_REPLACED/c $REPLACEMENT_TEXT_STRING" /tmp/foo

Tek tırnak yerine çift tırnak kullanımına dikkat edin.


yine de böyle tek tırnak işaretleri kullanabilirsiniz: sed -i '/ TEXT_TO_BE_REPLACED / c' "$ VARIABLE" '' / tmp / foo
Alistair McIntyre

4

Şimdiye kadar verilen tüm cevaplar, değiştirilecek metin hakkında bir şeyler bildiğinizi varsayar ki bu da mantıklıdır, çünkü OP'nin sorduğu şey budur. Değiştirilecek metin hakkında hiçbir şey bilmediğinizi ve dosyada değiştirilmesini istemediğiniz aynı veya benzer içeriğe sahip ayrı bir satır olabileceğini varsayan bir yanıt sağlıyorum. Ayrıca, değiştirilecek hattın hat numarasını bildiğinizi varsayıyorum.

Aşağıdaki örnekler metnin belirli satır numaralarına göre kaldırılmasını veya değiştirilmesini gösterir:

# replace line 17 with some replacement text and make changes in file (-i switch)
# the "-i" switch indicates that we want to change the file. Leave it out if you'd
#   just like to see the potential changes output to the terminal window.
# "17s" indicates that we're searching line 17
# ".*" indicates that we want to change the text of the entire line
# "REPLACEMENT-TEXT" is the new text to put on that line
# "PATH-TO-FILE" tells us what file to operate on
sed -i '17s/.*/REPLACEMENT-TEXT/' PATH-TO-FILE

# replace specific text on line 3
sed -i '3s/TEXT-TO-REPLACE/REPLACEMENT-TEXT/'

3

yapılandırma dosyalarının yönetimi için

skensell cevabından esinlenerek bu çözümü buldum

configLine [searchPattern] [replaceLine] [filePath]

olacak:

  • yoksa dosyayı oluştur
  • searchPattern'in eşleştiği tüm satırı (tüm satırları) değiştir
  • desen bulunamazsa dosyanın sonuna replaceLine ekleyin

İşlev:

function configLine {
  local OLD_LINE_PATTERN=$1; shift
  local NEW_LINE=$1; shift
  local FILE=$1
  local NEW=$(echo "${NEW_LINE}" | sed 's/\//\\\//g')
  touch "${FILE}"
  sed -i '/'"${OLD_LINE_PATTERN}"'/{s/.*/'"${NEW}"'/;h};${x;/./{x;q100};x}' "${FILE}"
  if [[ $? -ne 100 ]] && [[ ${NEW_LINE} != '' ]]
  then
    echo "${NEW_LINE}" >> "${FILE}"
  fi
}

çılgın çıkış durumu büyüsü https://stackoverflow.com/a/12145797/1262663 adresinden geliyor.


2
bash-4.1$ new_db_host="DB_HOSTNAME=good replaced with 122.334.567.90"
bash-4.1$ 
bash-4.1$ sed -i "/DB_HOST/c $new_db_host" test4sed
vim test4sed
'
'
'
DB_HOSTNAME=good replaced with 122.334.567.90
'

iyi çalışıyor


1

Benim makefile bunu kullanın:

@sed -i '/.*Revision:.*/c\'"`svn info -R main.cpp | awk '/^Rev/'`"'' README.md

Not: YAPMAYIN siz "Revizyon" olarak tanımlanan model değişecek eğer gerçekten -i değişiklikler dosyasında metin ... yani, sen de yerine deseni değişecek unutma.

Örnek çıktı:

John Doe tarafından yazılan Abc-Project

Revizyon: 1190

Dolayısıyla, "Revizyon: 1190" kalıbını ayarlarsanız, bunları yalnızca "Revizyon:" olarak tanımladığınızla aynı değildir.


1
cat find_replace | while read pattern replacement ; do
sed -i "/${pattern}/c ${replacement}" file    
done 

find_replace dosyası, 2 sütun, eşleşecek desenli c1, yedekli c2, sed döngüsü, değişken 1 modelinden birini içeren her satırı değiştirir


Hayır, bu birkaç açıdan yanlış. Gerçekleştirmek sedistediğiniz tüm değişiklikleri içeren bir komut dosyasıyla bir kez çalıştırın . sed -iAynı dosya üzerinde tekrar tekrar çalıştırmak korkunç bir antipattern.
tripleee

0

Yukarıdakine benzer ..

sed 's/[A-Za-z0-9]*TEXT_TO_BE_REPLACED.[A-Za-z0-9]*/This line is removed by the admin./'

3
Değişiklikler O FOO=TEXT_TO_BE_REPLACEDkadar FOO=This line ...böylece şartname karşılamıyor.
Jens

Evet .. İhtiyacımız tüm satırı 'Bu satır yönetici tarafından kaldırıldı' ile değiştirmek. anahtar pattren 'TEXT_TO_BE_REPLACED' bulursak. Yukarıdaki komut tatmin edicidir. Anlayışım yanlışsa beni düzeltin .. @Jens
Annapureddy Hari

@AnnapureddyHari, arama dizesinden önceki veya sonraki metin A-Za-z0-9 dışında bir şey içeriyorsa bu cevap çalışmaz. Jens'in işaret ettiği gibi, eşit bir işaret varsa başarısız olur. "FOO =" kısmı kalacak; tüm satırı değiştirmediniz. Bu kod, dosyada ne olabileceği konusunda kısa görüşlüdür. Joker karakter demek istiyorsan, Thor'un cevabının gösterdiği gibi joker karakter koymalısın.
msouth

0

Aşağıdaki komut benim için çalışıyor. Hangi değişkenlerle çalışıyor

sed -i "/\<$E\>/c $D" "$B"

Ama benim yeni gereksinimim değiştirirken SKIP yorumlu (# ile başlar) satırı. Komple satırı değiştirdiğimizde, bu, yorum yapılan satırların da yerini alacak ve yinelenen özelliklerle sonuçlanacaksınız. Bunun için bir çözüm varsa lütfen bana bildirin.
Ritesh Borkar

-1

Ben sık sık sadece hiçbir şey \"ile literal alıntı yerine kullandığınız dosyalardan veri ayıklamak için regex kullanın //:-)

cat file.csv | egrep '^\"([0-9]{1,3}\.[0-9]{1,3}\.)' | sed  s/\"//g  | cut -d, -f1 > list.txt
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.