bash - boşluğu yeni satırla değiştir


70

Boşlukları aşağıdaki gibi yeni bir girişle nasıl değiştirebilirim:

/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5 vb...

Aşağıdakileri elde etmek için:

/path/to/file
/path/to/file2
/path/to/file3
/path/to/file4
/path/to/file5

Not

Bu soruyu diğer kullanıcılara yardımcı olmak için gönderiyorum, bu soruyu yazmaya başlayana kadar UNIX SE'de yararlı bir cevap bulmak kolay değildi. Bundan sonra aşağıdakileri buldum:

İlgili soru

Yeni bir satırı nasıl bulabilir ve değiştirebilirim?



ls / yol / to / | xargs yankı | sed 's / \ s \ + / \ n / g'
SD.

Yanıtlar:



20

Bu durumda printf kullanırdım:

printf '%s\n' /path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5

Boşluk varsa içinde yolların biri, sen alanlarda bölünmüş engellemek amacıyla bu dosyayolu alıntılayabilirsiniz:

printf '%s\n' /path/to/file '/path/to/file with spaces' /path/to/another/file

Metni genel olarak dönüştürmek triçin mevcut bir cevabın kapsamı dahilinde en iyi seçeneğinizdir.


1
Gelecekten kısa bir not: Bu çözümü gönderdiğiniz için teşekkürler, "echo" kullanmaya kıyasla benim için çok güvenilirdi.
Liesmith

5

Ayırıcı olarak boşluk içeren bir dize bulunduğunu varsayalım:

newline_separated=${space_separated// /$'\n'}

Ancak muhtemelen yanlış soruyu soruyorsunuz. (Mutlaka gerekli değildir, örneğin bu bir makefile'de ortaya çıkabilir.) Dosyadan boşlukla ayrılmış bir liste gerçekten işe yaramazsa: dosya adlarından biri boşluk içeriyorsa ne olur?

Bir program dosya isimlerini argüman olarak alırsa, onları boşluklarla birleştirmeyin. "$@"Onlara birer birer erişmek için kullanın . Her ne kadar echo "$@"baskılar arasında boşluk olan argümanlar, o nedeniyle olduğunu echo: o ayırıcı olarak boşluk ile argümanları basar. somecommand "$@"dosya adlarını komuta ayrı argümanlar olarak iletir. Bağımsız değişkenleri ayrı satırlara yazdırmak istiyorsanız,

printf '%s\n' "$@"

Boşluklu dosya adlarınız varsa ve bunları üzerinde çalışmak üzere bir diziye koymak istiyorsanız, değeri karakterlere bölmek için işaretsiz bir değişken genişletme kullanabilirsiniz IFS(joker karakter genişletmesini devre dışı bırakmanız gerekir set -f, aksi takdirde glob desenler değerinde genişletilecektir):

space_separated_list='/path/to/file1 /path/to/file2 /path/to/file3'
IFS=' '; set -f
eval "array=(\$space_separated_list)"
for x in "${array[@]}"; do 

Bunu, -fayarı ve yapılan işlemin değerini geri yükleyen bir fonksiyonda saklayabilirsiniz IFS:

split_list () {
  local IFS=' ' flags='+f'
  if [[ $- = *f* ]]; then flags=; fi
  set -f
  eval "$1=($2)"
  set $flags
}
split_list array '/path/to/file1 /path/to/file2 /path/to/file3'
for x in "${array[@]}"; do 

Buna doğru cevabı değiştirme. Sanırım boşlukla ayrılmış bir listeye nasıl girdiğimi araştırmak ve bu bilgiyi başka bir şekilde almak daha doğru. Birazcık yorumunu biraz yorumlayarak, yerel var IFS veya $ - = f koşulu gibi şeyleri neler yaptığını bize söyleyerek benim gibi öğrenciler için çok iyi olurdu . Beş kere bash kullanan bir insan böyle şeyleri bilmiyor.
laconbass

@ laconbass Kısa bir açıklama ekledim. Yukarı bak set -fve IFSbash kılavuzunda tüm ayrıntıları istiyorum. Ayrıca bkz. Unix.stackexchange.com/questions/16192/…
Gilles

@ Guiller Bu kısa açıklama benim için yeterli, ve bunun birçokları için olacağını düşünüyorum. Saat Ty
laconbass

IFSyerel olarak ayarlama geçerli olmaz
Eliran Malka

@EliranMalka Bununla ne demek istediğinizi anlamadım. Bir senaryo olması gerektiği gibi davranmıyorsa, burada bir soru sorabilirsiniz.
Gilles,

4

Pragmatik olun, sed kullanın !!

sed 's/\s\+/\n/g' file

Yukarıdaki, bir veya daha fazla boşluk karakterinin (\ s +) newline (\ n) ile değiştirileceğini söylüyor

Bu az çok:

'substitute /one space or more/ for /newline/ globally'

1
değişim yerine alternatifi kullanın, aslında s nin anlamı budur!
Rob,

@Rob teşekkürler, başkalarının cevaplarını düzenleyebileceğinizi unutmayın.
MGP,

1
Metin arasında birden fazla boşluk varsa, o zaman boş satırlar alırsınız. Tam olarak bir alana atanmış en az bir alanla eşleşmek istediğinizi belirtmek için \ s'den sonra '+' eklemeniz gerekir. yani. sed 's / \ s + / \ n / g'
DarkHeart

4

tr@Laconbass'dan alternatif olarak , xargsbu durumda da kullanabilirsiniz :

echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4  /path/to/file5"\
| xargs -n1

Bunun avantajı, çalışmayan çoklu boşluklarla bile çalışmasıdır tr.


0

İşte nasıl yaptım:

echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5" | sed 's/ /\
'/g

Komutta ters eğik çizgiden sonra Enter tuşunun kullanıldığına dikkat edin sed.


Ne prons ve eksileri vardır sedüzerinde tr?
laconbass

Konfor seviyeniz :-) sedBasitçe karakter çevirmekten ziyade editör olduğu için daha fazlasını yapabileceğinizi düşünüyorum .
unxnut

4
sedçok daha fazlasını yapabilir, ancak bunun için tamamen overkill. trBU iş için doğru araçtır, ancak bilgi sedve regexes bilgi kesinlikle daha sonra kullanışlı olacak!
Rob,

0

Satırı varsayarsak, diğer bir yaklaşım denilen bir değişkendir line:

for path in $line;do echo $path;done

Bu, Bash'in argümanlarını varsayılan olarak boşluklara ayırdığı ve varsayılan echoolarak girişine yeni bir satır eklediği gerçeğini kullanır .


Bu soruyu yayınlamadan ve işe yaramadan önce bunu ubuntu sistemimde denedim.
Laconbass

0
echo word1 word2 ... | sed -e 'y/ /\n/;P;D'

Tek boşlukla ayrılmış sözcükleri ayrılmış yeni satıra dönüştürmek için başka bir yöntemdir.


-1

Aşağıdaki betiğin anlaşılması ve kullanımı kolaydır.

cat filename | tr ' ' '\n' | tee filename

2
Cevabınızın özü ( tr), kabul edilen cevabın aynısıdır. Cevabınızın yanında aşağıdaki hususlar vardır: a) Komut 4 boşlukla (-> işaretleme düzeni) girintili değildir. B) Kullanımınız catişe yaramaz (yerine kullanabilirsiniz < filename tr ' ' '\n'). c) Çıktı dosya adınız, giriş dosya adıyla aynı. Bununla bir veri yarışı yaratırsınız.
maxschlepzig

1
Maxschlepzig'in doğru analizinden ayrı olarak, bu bir betik değil, kod kodlu bir dizi bağlı komuttur (betik inşallah giriş ve çıkış için iki parametre kullanmak ve kullanmak için kabuğu belirten bir başlığa sahip olacaktır). Bunun dışında evimdeki her 3 kişiden 2'si anlaşılmasını kolay bulmuyor. Belki bu temsili değildir, ancak kendinizin anladığınız (veya bu durumda anladığınızı sandığınız) bir şeyin her zaman kolay gözüktüğünü unutmayın.
Anthon
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.