Bash'de bir dizeden yeni satır nasıl kaldırılır


110

Aşağıdaki değişkene sahibim.

echo "|$COMMAND|"

hangi döner

|
REBOOT|

İlk satırı nasıl kaldırabilirim?


7
Bu neden bir dupe olarak işaretlendi? Bu soru, bir satır başının kaldırılmasıyla ilgilidir. Bağlantı oluşturduğu iddia edilen yinelenen soru, boşlukların kaldırılmasıyla ilgilidir ve yalnızca tesadüfen satır başlarından bahseder.
Michael Scheper

1
@MichaelScheper kabul etti ve yeniden açıldı.
fedorqui

Buradaki terminoloji tuhaf. Unix satır sonlandırma karakterine \n(onaltılık 0x0A) yalan besleme (LF) denir; bu, \rWindows'ta ve birçok ağ protokolünde CR LF iki baytlık satır sonlandırma dizisinde ilk bayt olarak kullanılan karakter taşıma dönüşünden (CR) (onaltılık 0x0D) farklıdır .
üçlü

Yanıtlar:


114

Altında bazı bashizmler var:

trKomut ile değiştirilebilir ya da // bashism :

COMMAND=$'\nREBOOT\r   \n'
echo "|${COMMAND}|"
|
   OOT
|

echo "|${COMMAND//[$'\t\r\n']}|"
|REBOOT   |

echo "|${COMMAND//[$'\t\r\n ']}|"
|REBOOT|

Bkz Parametre Genişletme ve alıntı bash adamı sayfasında:

man -Pless\ +/\/pattern bash
man -Pless\ +/\\\'string\\\' bash

man -Pless\ +/^\\\ *Parameter\\\ Exp bash
man -Pless\ +/^\\\ *QUOTING bash

Daha ileri...

@AlexJordan tarafından sorulduğu gibi, bu belirtilen tüm karakterleri bastıracaktır . Peki ya $COMMANDboşluk içeriyorsa ...

COMMAND=$'         \n        RE BOOT      \r           \n'
echo "|$COMMAND|"
|
           BOOT      
|

CLEANED=${COMMAND//[$'\t\r\n']}
echo "|$CLEANED|"
|                 RE BOOT                 |

shopt -q extglob || { echo "Set shell option 'extglob' on.";shopt -s extglob;}

CLEANED=${CLEANED%%*( )}
echo "|$CLEANED|"
|                 RE BOOT|

CLEANED=${CLEANED##*( )}
echo "|$CLEANED|"
|RE BOOT|

kısaca:

COMMAND=$'         \n        RE BOOT      \r           \n'
CLEANED=${COMMAND//[$'\t\r\n']} && CLEANED=${CLEANED%%*( )}
echo "|${CLEANED##*( )}|"
|RE BOOT|

Not: adres extglobseçeneği (etkin olması shopt -s extglobkullanım amacıyla) *(...)sözdizimi.


1
BASH'daki bir değişkenden satır beslemelerini ayırmanın yolu budur. Diğer cevaplar gereksiz yere fazladan bir TR sürecini çağırıyor. BTW, bitiş alanlarını kaldırma ek avantajına sahiptir!
ingyhere

1
Ayrıca bir dizeden dahili boşlukları da kaldırdığını unutmayın ... şunu COMMAND="RE BOOT"; echo "|${COMMAND//[$'\t\r\n ']}|"döndürür|REBOOT|
Alex Jordan

2
@AlexJordan Evet, bu istenen bir özellik : Bunu \nönlemek için daha sonra boşluğu çırpabilirsiniz : COMMAND="RE BOOT"; echo "|${COMMAND//[$'\t\r\n']}|"geri dönecektir |RE BOOT|.
F. Hauri

2
Desen nasıl işliyor ${COMMAND//[$'\t\r\n']}? ${COMMAND//[\t\r\n]}Basitçe işe yarayacağını düşündüm , ama olmadı. $Tek tırnaklar da ne sembolü ve nedir ?
haridsv

1
$ '' Sözdizimiyle ilgili olarak, bu ANSI C alıntıdır (wjordans yanıtında belirtilmiştir).
chuckx

81
echo "|$COMMAND|"|tr '\n' ' '

satırsonu satırını (POSIX / Unix'te bu bir satır başı değildir) bir boşlukla değiştirir.

Dürüst olmak gerekirse bash'dan daha aklı başında bir şeye geçmeyi düşünürdüm. Veya ilk etapta bu hatalı biçimlendirilmiş verileri oluşturmaktan kaçınmak.

Hmmm, bu da verilerin nereden geldiğine bağlı olarak korkunç bir güvenlik açığı gibi görünüyor.


Tarih aynı sunucuda bulunan bir curl isteğinden geliyor. Bunu yeni bir değişkene nasıl ekleyebilirim? newvar = $ (echo "| $ COMMAND |" | tr '\ n' '')
Matt Leyland

2
Evet. Ama lütfen bana rastgele kişilerin sunucunuzu parola olmadan uzaktan yeniden başlatmalarına izin vermediğini söyleyin ...
Robin Green

31
Neden boşlukla değiştirmek yerine düşürmektr -d '\n' için kullanmadınız
F. Hauri

3
Lütfen işe yaramaz boruları kırbaçlayın! tr '\n' ' ' <<< "|$COMMAND|"Bunun yerine kullanınecho ... | ...
F. Hauri

12
@ F.Hauri: veya işe yaramaz "|${COMMAND//$'\n'}|"
tr'ler

75

Tüm satır başlarını kaldırarak değişkeninizi temizleyin:

COMMAND=$(echo $COMMAND|tr -d '\n')

22
Bu şerit hat beslemiyor mu? Onun tr -d '\r'yerine olması gerekmiyor mu?
Izzy

3
Yorumlanmamış bir değişkeni yankılamak tüm IFS karakterlerini (varsayılan olarak satırsonu, boşluk, sekme) kaldırır. Yani bunu yapacaksanız, tüm IFS karakterlerinin düştüğünün ve buna ihtiyacınız olmadığının farkında olmalısınız tr. Basitçe COMMAND=$(echo $COMMAND)benzer bir etki verecektir. Muhtemelen şeytan yeni bir süreci başlatırken ortaya çıkar, ancak yine de oldukça kısa ve insan gözü için tatlıdır ve hayatınızda ayıracak bir veya iki saniyeniz varsa, vuruşu almaya istekli olabilirsiniz :-).
Mike S

Soruyu "satır besleme" olacak şekilde güncelledim, çünkü örneği bunun bir satır başı değil, satır besleme olduğunu gösterdi. Bu cevap hala doğru, ancak "satır başı" yerine "satır besleme" şeklinde güncellenmesi gerekebilir mi?
Benjamin W.

8

Kullanarak bash:

echo "|${COMMAND/$'\n'}|"

(Bu sorudaki kontrol karakterinin bir satırsonu ( \n) değil bir 'satırsonu' ( ) olduğuna dikkat edin \r; ikincisi REBOOT|tek bir satırda çıktı alacaktır .)

açıklama

Bash Kabuğu Parametre Genişletmesini kullanır ${parameter/pattern/string}:

Desen sadece Dosyaismi gibi bir kalıp üretmek için genişletilir. Parametre genişletilir ve değerine karşı en uzun model eşleşmesi string ile değiştirilir . [...] Dizge boş ise, kalıp eşleşmeleri silinir ve / sonraki kalıp çıkarılabilir.

Ayrıca bir satırsonu olarak belirtmek için $'' ANSI-C alıntı yapısını kullanır $'\n'. Doğrudan bir satırsonu kullanmak da işe yarar, ancak daha az hoş:

echo "|${COMMAND/
}|"

Tam örnek

#!/bin/bash
COMMAND="$'\n'REBOOT"
echo "|${COMMAND/$'\n'}|"
# Outputs |REBOOT|

Veya yeni satırlar kullanarak:

#!/bin/bash
COMMAND="
REBOOT"
echo "|${COMMAND/
}|"
# Outputs |REBOOT|

6

Benim için işe yarayan şey echo $testVar | tr "\n" " "

TestVar değişkenimi / kod çıktımı nerede içeriyor


4

Tr kullanarak ve sed kullanarak \ r dahil olmak üzere birden çok karakterin çıkarılması örneğini göstermek için yanıt ekleniyor. Ve hexdump kullanarak gösteriliyor.

Benim durumumda |awk '{print $2}', satırdaki son öğenin awk baskısı ile biten bir komutun bir carriage-return \ r ve tırnak işaretleri içerdiğini buldum .

Kullandığım sed 's/["\n\r]//g'satırbaşı ve tırnak hem şerit.

Ben de kullanabilirdim tr -d '"\r\n'.

sed -zSatır besleme karakterlerini kaldırmak \ n istiyorsa ilginçtir .

$ COMMAND=$'\n"REBOOT"\r   \n'

$ echo "$COMMAND" |hexdump -C
00000000  0a 22 52 45 42 4f 4f 54  22 0d 20 20 20 0a 0a     |."REBOOT".   ..|

$ echo "$COMMAND" |tr -d '"\r\n' |hexdump -C
00000000  52 45 42 4f 4f 54 20 20  20                       |REBOOT   |

$ echo "$COMMAND" |sed 's/["\n\r]//g' |hexdump -C
00000000  0a 52 45 42 4f 4f 54 20  20 20 0a 0a              |.REBOOT   ..|

$ echo "$COMMAND" |sed -z 's/["\n\r]//g' |hexdump -C
00000000  52 45 42 4f 4f 54 20 20  20                       |REBOOT   |

Ve bu konuyla ilgilidir: Satır başı, satır besleme ve form besleme nedir?

  • CR == \ r == 0x0d
  • LF == \ n == 0x0a

3

Basitçe kullanabilirsiniz echo -n "|$COMMAND|".


2

Extglob seçeneği etkinken bash kullanıyorsanız, sadece sondaki beyaz boşluğu şu şekilde kaldırabilirsiniz:

shopt -s extglob
COMMAND=$'\nRE BOOT\r   \n'
echo "|${COMMAND%%*([$'\t\r\n '])}|"

Bu çıktılar:

|
RE BOOT|

Veya sadece baştaki boşlukları değiştirmek için %% 'yi ## ile değiştirin.


1
Bu, docker komutundan aldığım bazı garip çıktılarla bir cazibe gibi çalıştı. Çok teşekkürler!
develCuy
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.