Perintah dan gema Cat

14

Saya ingin menggabungkan output dari gema dengan konten file. Saya sudah mencoba perintah berikut:

echo "abc" | cat 1.txt > 2.txt

tetapi 2.txtfile tersebut hanya berisi konten dari 1.txt. Mengapa itu tidak berhasil?

Ringger81
sumber
3
Program seperti cathanya membaca dari input standar jika mereka tidak memiliki argumen nama file.
Barmar

Jawaban:

23

Ini tidak berfungsi karena catprogram dalam urutan pipa Anda tidak diperintahkan untuk membaca echooutput program dari input standar.

Anda dapat menggunakan -nama file semu untuk menunjukkan input standar cat. Dari man catpada instalasi msys2:

EXAMPLES
       cat f - g
              Output f's contents, then standard input, then g's contents.

Jadi coba

echo "abc" | cat - 1.txt > 2.txt

sebagai gantinya.

mvw
sumber
21

Seperti dicatat oleh orang lain, perintah asli Anda gagal karena cat 1.txtmengabaikan input standarnya. Baik menunjukkan bahwa itu harus menjadi argumen pertama ( cat - 1.txt), atau menggunakan pengalihan blok untuk mengarahkan echo abc dan cat 1.txt bersama - sama. Yakni:

{ echo abc; cat 1.txt; } > 2.txt 

Kutipan yang relevan dari manual ( man bash):

Compound Commands Perintah
majemuk adalah salah satu dari yang berikut ini. Dalam kebanyakan kasus, daftar dalam deskripsi perintah dapat dipisahkan dari sisa perintah oleh satu atau lebih baris baru, dan dapat diikuti oleh baris baru di tempat tanda koma.

(daftar)

    daftar dieksekusi dalam lingkungan subkulit (lihat LINGKUNGAN PERINTAH EKSEKUSI di bawah). Tugas variabel dan perintah bawaan yang mempengaruhi lingkungan shell tidak tetap berlaku setelah perintah selesai. Status kembali adalah status keluar dari daftar.

{daftar; }

    daftar hanya dieksekusi di lingkungan shell saat ini.  daftar harus diakhiri dengan baris baru atau titik koma. Ini dikenal sebagai perintah grup . Status kembali adalah status keluar dari daftar . Perhatikan bahwa tidak seperti metacharacters (dan ), {dan }adalah kata - kata yang dicadangkan dan harus terjadi di mana kata yang dilindungi diizinkan untuk dikenali. Karena mereka tidak menyebabkan istirahat kata, mereka harus dipisahkan dari daftar oleh spasi putih atau karakter meta shell lainnya.

Opsi pertama (lingkungan subkulit) memiliki banyak efek samping, kebanyakan jika tidak semuanya tidak relevan dengan skenario Anda; namun, jika Anda hanya perlu mengarahkan sejumlah output perintah, maka Opsi # 2 di sini (perintah grup) lebih disukai.

Nubarke
sumber
7
( echo "abc"; cat 1.txt ) > 2.txt

Anda menyalurkan output gema ke kucing, tetapi kucing tidak menggunakan input, dan mengabaikannya. Sekarang perintah dijalankan satu demi satu, dan hasilnya dikelompokkan (tanda kurung) dan diarahkan ke 2.txt.

Gerard H. Pille
sumber
1
Jawaban ini dapat ditingkatkan dengan menjelaskan cara kerjanya dan mengapa upaya awal OP tidak berhasil.
Bob
OK, cobalah.
Gerard H. Pille
5
Subkulit tidak secara tegas diperlukan di sini, mungkin akan lebih baik menggunakan perintah grup. Lihat jawaban saya untuk lebih jelasnya.
Nubarke
Ah, tapi aku tidak akan pernah menggunakan bash.
Gerard H. Pille
1
@ GerardH.Pille: Sementara jawaban Daniel mengutip bash(1), itu menjelaskan perilaku yang harus didukung oleh setiap shell yang mendukung POSIX .
G-Man Mengatakan 'Reinstate Monica'
2

Perintah cat 1.txtAnda tidak melakukan apa pun dengan output dari echo "abc".

Sebaliknya: (echo "abc"; cat 1.txt) > 2.txt akan menulis output dari kedua perintah ke 2.txt.

muclux
sumber
Jawaban ini dapat ditingkatkan dengan menjelaskan cara kerja alternatif yang disarankan.
Bob
1

Dalam setiap shell POSIX Anda bisa menggunakan substitusi perintah untuk digunakan cat filesebagai input untuk echo:

echo $(cat file1.txt) "This Too"

Di Bash Anda bisa menggunakan subtitusi proses dan menggunakan gema sebagai "file" lain untuk cat, seperti di:

cat file1.txt <(echo This Too)

dan kemudian pipa atau redirect output sesuai keinginan Anda.

Seperti setiap jawaban lainnya katakan, kucing mengabaikan stdin jika punya file untuk dilihat. (Saya juga suka jawaban Daniel & mvw, +1 untuk mereka)

Xen2050
sumber
1
Jawaban ini dapat ditingkatkan dengan menjelaskan mengapa upaya awal OP tidak berhasil (dan karena itu mengapa ini diperlukan).
Bob
1
The <(command)konstruksi adalah ekstensi bash. Ini bukan POSIX, jadi Anda tidak bisa mengandalkannya dalam skrip yang seharusnya dijalankan /bin/sh.
Rhialto mendukung Monica
0

Hanya tebakan, tetapi sepertinya Anda memiliki proses berulang, yang merupakan kandidat yang baik untuk alias atau fungsi. Alias ​​biasanya merupakan jalan pintas untuk menjalankan perintah bash, seperti singkatan, pada aliran input tunggal sebagai argumennya.

alias hg="history | grep"

Namun, dalam hal ini, fungsi akan lebih mudah dibaca, karena Anda menggabungkan beberapa input stream, diskrit (2) serta beberapa perintah bash. Anda memiliki dua argumen, yang pertama adalah string dan yang lainnya adalah sebuah filepath. Pada akhirnya, Anda ingin hasilnya ditulis ke aliran keluaran stdout.

Dari prompt CLI, ketik ini:

# ecat()        
{
echo ${1}
cat ${2}
}

Fungsi Anda bernama ecat, yang mudah diingat.

Sekarang Anda dapat memanggil sebagai

ecat "abc" 1.txt

Untuk menambahkan, cukup berikan tujuan keluaran yang berbeda ke stdout:

ecat "abc" 1.txt >> 2.txt

Operator pengalihan append '>>' akan menambahkan output ke akhir file yang ditentukan.

Jika Anda menyukainya, tambahkan file ~ / .bashrc Anda untuk digunakan kembali.

declare -f ecat >> ~/.bashrc

Itu juga berarti Anda dapat menghias, dll, dalam definisi fungsi Anda.

Juga ide yang baik untuk melindungi file dari ditimpa dengan menambahkan ini ke ~ / .bashrc Anda

set noclobber
FrDarryl
sumber
2
Agar fungsi Anda berperilaku baik, Anda harus menggunakan "$1"dan "$2". Dalam konteks ini, kurung kurawal tidak ada gunanya. Lihat ${name}tidak berarti apa yang Anda pikirkan itu tidak ... .
G-Man Mengatakan 'Reinstate Monica'
1
Bagaimana noclobbersaran itu responsif terhadap pertanyaan yang ada? (Saya juga sangat tidak yakin bahwa itu saran yang bagus - memodifikasi perilaku global cenderung mematahkan skrip / saran / praktik yang dibangun dengan mempertimbangkan default).
Charles Duffy
0

Kode berikut juga akan berfungsi:

echo abc >> 1.txt && cat 1.txt > 2.txt

Output dari echo abc akan ditambahkan ke 1.txt dengan >> Setelah itu && akan memerintahkannya untuk menjalankan set perintah berikutnya yang akan menghasilkan 1.txt dan kemudian output ke 2.txt . Pada dasarnya, ini menambahkan output dari perintah pertama ke dalam 1.txt dan kemudian mengirimkan output dari 1.txt ke dalam 2.txt.

Jika Anda ingin abc muncul terlebih dahulu, Anda dapat menggunakan kode berikut:

echo abc >> 2.txt && cat 1.txt >> 2.txt
Nasir Riley
sumber
1
Ini akan (1) menempatkan abcdi bawah dari 2.txt; pertanyaan menginginkannya di atas. (2)  memodifikasi yang 1.txtberkas; ini tidak bisa diterima.
G-Man Mengatakan 'Reinstate Monica'
Di mana katanya? Ringger81 tidak pernah menentukan di mana dalam 2.txt dia ingin abc muncul. Anda mengasumsikan hal-hal yang pertanyaannya tidak pernah nyatakan.
Nasir Riley
(1) OK, Anda menaikkan poin yang valid di # 1. Sementara pertanyaan menyebutkan "output dari gema" sebelum "konten file" dalam teks, dan kemudian menempatkan echosebelum catdalam perintah sampel, saya kira itu tidak pernah secara tepat, secara eksplisit , mengatakan bahwa ia ingin output dari gema sebelum isi dari file input. Sepertinya kebanyakan orang menafsirkannya seperti itu. (2)  1.txtadalah file input. Pertanyaannya tidak mengatakan apa pun tentang memodifikasi 1.txt. Fakta bahwa file input tidak boleh dimodifikasi tidak perlu dikatakan lagi.
G-Man Mengatakan 'Reinstate Monica'
Saya bisa mengerti maksud Anda tentang tidak memodifikasi file imput. Kode kedua saya akan mencapai efek yang diinginkan tanpa melakukannya.
Nasir Riley
1
Membuka file, menambahkannya, menutupnya , membukanya lagi, menambahkannya lagi ... mengapa melakukan itu daripada hanya membukanya sekali dan menjaga pengalihan di tempat untuk kedua operasi?
Charles Duffy