استخدام أنابيب شل مع Go

أن تكون مواطنًا صالحًا في سطر الأوامر يعني استخدام الأنابيب.

باستخدام الشريط العمودي|يمكننا تمرير إخراج أمر ما كمدخل لأمر آخر ، وتسلسل أوامر متعددة لتوفير مخرجات فريدة.

لقد قمت بعمل دورتين تعليميتين تستخدمان الأنابيب كمدخلات ، بناءغوكوسايوجلولكات، لكنني لم أصف بالتفصيل عملية الحصول على مدخلات من أنبوب ، لذا إليك مقالة حول هذا الموضوع.

هذا مثال:

package main

import ( “bufio” “fmt” “io” “os” )

func main() { info, err := os.Stdin.Stat() if err != nil { panic(err) }

<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">info</span>.<span style="color:#a6e22e">Mode</span>()<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">ModeCharDevice</span> <span style="color:#f92672">!=</span> <span style="color:#ae81ff">0</span> <span style="color:#f92672">||</span> <span style="color:#a6e22e">info</span>.<span style="color:#a6e22e">Size</span>() <span style="color:#f92672">&lt;=</span> <span style="color:#ae81ff">0</span> {
	<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"The command is intended to work with pipes."</span>)
	<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"Usage: fortune | gocowsay"</span>)
	<span style="color:#66d9ef">return</span>
}

<span style="color:#a6e22e">reader</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">bufio</span>.<span style="color:#a6e22e">NewReader</span>(<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Stdin</span>)
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">output</span> []<span style="color:#66d9ef">rune</span>

<span style="color:#66d9ef">for</span> {
	<span style="color:#a6e22e">input</span>, <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">reader</span>.<span style="color:#a6e22e">ReadRune</span>()
	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">==</span> <span style="color:#a6e22e">io</span>.<span style="color:#a6e22e">EOF</span> {
		<span style="color:#66d9ef">break</span>
	}
	<span style="color:#a6e22e">output</span> = append(<span style="color:#a6e22e">output</span>, <span style="color:#a6e22e">input</span>)
}

<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">j</span> <span style="color:#f92672">:=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">j</span> &lt; len(<span style="color:#a6e22e">output</span>); <span style="color:#a6e22e">j</span><span style="color:#f92672">++</span> {
	<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Printf</span>(<span style="color:#e6db74">"%c"</span>, <span style="color:#a6e22e">output</span>[<span style="color:#a6e22e">j</span>])
}

}

دعونا نفحص كيف يعمل هذا. أول خط مثير للاهتمام:

info, err := os.Stdin.Stat()

os.Stdin، مثل Stdout و Stderr ، هو مفتوحملف. يشير إلى واصف ملف الإدخال القياسي.

Stat()هي طريقة للملف تقوم بإرجاع ملفمعلومات الملفوصف الملف ، وتوفير المعلومات بما في ذلك الوضع وحجم الملف.

القطعة التالية المثيرة للاهتمام هي

info.Mode()&os.ModeCharDevice != 0

FileInfo.Mode()إرجاع الuint32قناع يحدد وضع الملف والأذونات كقيمة ثابتة (https://golang.org/pkg/os/#FileMode).

استخدم طريقة البت باستخدام AND لتحديد ما إذا كان وضع الملف هو os.ModeCharDevice. هذه طريقة للتأكد من أن الملف يشير إلى ملفModeCharDevice، جهاز أحرف Unix (المحطة). منذ الملف يشير إلىos.Stdin، نحن في الأساس نستبعد المدخلات كونها أنبوب

يقوم Bitwise بإرجاع 0 إذا كان الوضع هوليسالثابت الذي نجتازه. يمكننا أيضا التحقق من

info.Mode()&os.ModeCharDevice == os.ModeCharDevice

هذا هو نفسه ، ولكن أكثر قابلية للقراءة.

إذا كان هذا خطأ ، فلدينا فحص إضافي لـ

info.Size() <= 0

الذي يتم دمجه مع الفحص السابق ، يتأكد من وجود أنبوب إدخال ، وأنه يحتوي بالفعل على بعض البايت.

يمكننا أيضا التحقق من

if info.Mode()&os.ModeNamedPipe != 0 {
	// we have a pipe input
}

وهذا سيضمن أن الإدخال يأتي من الأنبوب.

بعد ذلك يقوم البرنامج بإنشاء قارئ

reader := bufio.NewReader(os.Stdin)

bufioهي حزمة تنفذ الإدخال / الإخراج المخزن ، التفاف بشكل أساسيio.Readerوio.Writer.

نطلب منه أن يعطينا قارئًا مؤقتًا من os.Stdin ، باستخدام حجم المخزن المؤقت الافتراضي وهو 4096 بايت.

bufio.Readerيوفر العديد من الطرق لقراءة البيانات:ReadByteوReadBytesوReadLineوReadRuneوReadSliceوReadString.

يستخدم المثالReadRuneحتى تتمكن من إضافة كل قراءة رونية فيvar output []runeشريحة والتعامل معهايونيكودحرف من دون أي جهد.

اقرأ أكثر


المزيد من دروس Go: