Sed kelimesinde bir dizgideki karakterler arasına nasıl “&” koyabilirim?


Yanıtlar:


25

GNU ile sed:

sed 's/./\&&/2g'

( sYerini tutmaz her ( g) karakteri ( .(aynı olan) &ile başlar) &( \&) ancak ikinci bir oluşum elde etmek üzere ( 2)).

portably:

sed 's/./\&&/g;s/&//'

(her tekrarlamayı değiştirin, ancak &istemediğimiz her şeyi kaldırın ).

Bazı awkuygulamalarda (boş bir FS için davranış belirtilmediğinden POSIX değil):

awk -F '' -v OFS="&" '{$1=$1;print}'

( gawkve birkaç başka awkuygulamada, boş bir alan ayırıcısı kayıtları karakter bileşenlerine ayırır . Çıktı alanı ayırıcısı ( OFS) olarak ayarlanır &. $1Kaydın yeni alan ayırıcısıyla yeniden oluşturulmasını zorunlu kılmak için (kendisine) bir değer atarız yazdırmadan önce NF=NF, birçok awk uygulamasında da çalışır ve biraz daha etkilidir, ancak bunu yaptığınızda davranış şu anda POSIX tarafından belirtilmez).

perl:

perl -F -lape '$_=join"&",@F' 

( -peher satır için kodu çalıştırır ve sonucu yazdırır ( $_); -lsatır sonlarını otomatik olarak şeritler ve yeniden ekler; burada boş bir dize olan küme ayırıcıda girdi bölünmesiyle -adoldurulur . Sonuç, her karakteri bölmek , ardından '&' ile birleştirin ve satırı yazdırın.)@F-F@F

Alternatif:

perl -pe 's/(?<=.)./&$&/g' 

(öncesinde başka bir karakter olması koşuluyla her karakteri değiştirin (arkasına normal ifade operatörü (? <= ...))

zshKabuk operatörlerini kullanma :

in=12345
out=${(j:&:)${(s::)in}}

(yine, s::parametre genişletme bayrağını kullanarak boş bir alan ayırıcısına bölün ve ile birleştirin &)

Veya:

out=${in///&} out=${out#?}

(herşeyin (her karakterden önce) her birini ksh operatörünü &kullanarak değiştirin ${var//pattern/replacement}( kshboş bir desende başka bir şey anlamına gelir, ancak başka bir şey, ne olduğundan emin değilim bash) ve POSIX ${var#pattern}sıyırma ile ilkini kaldırın Şebeke).

ksh93Kabuk operatörlerini kullanma :

in=12345
out=${in//~(P:.(?=.))/\0&}

( ~(P:perl-like-RE)perl benzeri normal ifadeleri (perl veya PCRE'lerden farklı) kullanmak için ksh93 glob operatörü (?=.)olmak, ileriye dönük operatör olmak: bir karakteri onunla başka bir karakter izlemesi koşuluyla değiştirin ( \0) ve &)

Veya:

out=${in//?/&\0}; out=${out#?}

(her karakteri ( ?) &ve kendisi ( \0) ile değiştirin, ve gereksiz karakteri kaldırın)

bashKabuk operatörlerini kullanma :

shopt -s extglob
in=12345
out=${in//@()/&}; out=${out#?}

(aynı zshsen gerekmez dışında 'ın @()orada (İhtiyacınız olan Ksh topak operatör extglobiçinde bash)).


2
@AFSHIN, bu bir 012345girdi üzerinde çalışmaz
Stéphane Chazelas

1
bu çalışması gerekirawk -F '' -v OFS="&" 'NF=NF'
αғsнιη

1
@AFSHIN, ancak boş satırları kaldırın. Daha genel olarak, bir eylemi koşul olarak kullanırken ve yazdırılacak eylemin sonucunu
kastederken

1
Bunların her birinin nasıl çalıştığına dair hızlı bir açıklama ekleyebilir misiniz? Burada öğrenilecek bazı harika şeyler var gibi görünüyor, ancak bunları bu özel sorunun kapsamı dışında nasıl uygulayacağımızı görmek için çoğunu nerede araştırmaya başlayacağımı bile bilmiyorum.
IMSoP

1
@ StéphaneChazelas Harika, teşekkürler. Sed gibi şeyler için karmaşık dokümanları aramak bir sanattır, bu yüzden bazı uygulamalı örneklere sahip olmak, daha önce görmediğiniz yeni bitleri öğrenmenin harika bir yoludur.
IMSoP

15

Unix yardımcı programları:

fold -w1|paste -sd\& -

Açıklaması:

"fold -w1" - her bir giriş karakterini kendi satırına sarar

katlayın - her bir giriş satırını belirtilen genişliğe sığacak şekilde sarın

-w, --width = WIDTH 80 yerine WIDTH sütun kullan

%echo 12345|fold -w1
1
2
3
4
5

"paste -sd\& -"- &ayırıcı olarak giriş hatlarını birleştirir

yapıştır - dosya satırlarını birleştir

-s, --seri paralel yerine her seferinde bir dosya yapıştır

-d, --delimiters = LIST, SEKME yerine LIST'deki karakterleri yeniden kullanma

%fold -w1|paste -sd\& -
1&2&3&4&5

(Giriş birkaç satır içeriyorsa birleştirileceklerini unutmayın &)


2
Çok baytlı karakterler üzerinde hata. Deneyinecho "abcdeéèfg" | fold -1 | paste -sd\& -
Isaac

3
@Arrow Büyük olasılıkla , tam bir Unicode desteğine sahip olmayan buggy coreutils fold sürümünü kullanıyorsunuz . BSD katlama, coreutils (yani Fedora veya CentOS) RedHat yamalı sürümleri ve bunun BusyBox uygulaması, Unicode'u güzel bir şekilde işleyebilir.
zeppelin

5
Soru özellikle ilgili sed.
Alexander

6
@Alexander - bu doğrudur ve sedaşağıda bir dizi iyi yanıt bulunmaktadır. Ve görevin diğer yollarla nasıl çözülebileceğini göstermek için herhangi bir zarar görmüyorum.
zeppelin

@ StéphaneChazelas> POSIXly, fold -w 1 gerekir. Doğru, ekledim "-w", teşekkürler! "-", sırayla, gerekli değildirIf no file operands are specified, the standard input shall be used
zeppelin


9
sed 's/\B/\&/g'

\ B - Her yerde, ancak kelime sınırında eşleşir; yani soldaki karakter ve sağdaki karakter ya "kelime" karakterlerinden biri ya da her ikisi de "kelime dışı" karakterse eşleşir.

Bilgi: GNU sed manuel, düzenli ifade uzantıları .

Test yapmak:

sed 's/\B/\&/g' <<< '12345'
1&2&3&4&5

5
İlginç bir fikir ama soru, dizenin bir boşluk, bir nokta veya kelime sınırı oluşturabilecek herhangi bir şey içermediğini söylemiyor. Sadece "herhangi bir karakter" olarak yorumlanması gereken "karakterler arasında" yazıyor.
xhienne

4

Bu, diğer cevaplardan biraz daha yavaş olacak, ancak oldukça açık:

echo 12345 | perl -lnE 'say join "&", split //'

4

İşte başka bir yol. Sed ifadesinin ilk kısmı her karakteri yakalar ve sonra karakteri ve işareti ile değiştirir. İkinci bölüm ve işareti çizginin sonundan kaldırır.

echo 12345 | sed -r 's/(.)/\1\&/g;s/\&$//g'
1&2&3&4&5

Çok baytlı karakterler üzerinde de çalışır.


1
sedİki kez aramanıza gerek yok , bir sedkomut dosyasının birkaç komutu olabilir:sed -r 's/(.)/\1\&/g; s/\&$//g'
xhienne

xhienne, teşekkürler, TIL! Yanıt güncellendi.
Alexander
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.