<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>旷世的忧伤</title>
    <description>Huoty's blog，旷世的忧伤。专注于各类计算机技术，记录所感所想所思。分享 Linux 使用技巧，Python/PHP/C/C++ 等编程语言开发技术，以及其他程序设计经验</description>
    <link>https://donothing.site/</link>
    <atom:link href="https://donothing.site/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Mon, 13 Apr 2026 22:54:20 +0800</pubDate>
    <lastBuildDate>Mon, 13 Apr 2026 22:54:20 +0800</lastBuildDate>
    <generator>Jekyll v3.8.5</generator>
    
      <item>
        <title>还书</title>
        <description>&lt;h3 id=&quot;part-6542c3400e7&quot;&gt;梦起&lt;/h3&gt;

&lt;p&gt;滴，滴。朦胧中，夏南似乎听到了手机短信的铃声。但实在是太困了，不想去管，大周末的，何况都这么晚了，还有谁能有什么重要的事情找我么？&lt;/p&gt;

&lt;p&gt;滴，滴。不知过了多久，迷迷糊糊中铃声又响了。今天莫名其妙的有些困，还不到晚上十点，夏南就上了床，不知不觉间就睡着了。两次铃声响过，似把夏南扰的有些清醒了，伸手去摸手机，挣扎着睁开一只眼，看到有两条未读信息。&lt;/p&gt;

&lt;p&gt;第一条信息是：“您好，您于本店借阅的书将于今日 23:59:59 到期，烦请您如期归还，谢谢！”&lt;/p&gt;

&lt;p&gt;夏南一愣，我有在哪儿借过书吗？&lt;/p&gt;

&lt;p&gt;再看第二条信息：“您好，您是否于两天前给本店来过电话？实在抱歉，本店的电话系统出了点故障。如您有什么问题，可直接至店内咨询。”&lt;/p&gt;

&lt;p&gt;夏南坐起身来，怔了怔，闭眼细想起来。两天前好像确实有想起来借了本书快到期了，想着给它还掉，可怎么也记不起来书在哪里借的。那本书借来似乎也没看过，为什么会借也不清楚。翻开扉页，是一页白纸，上边有红章印上的电话，于是就打了电话过去，却没人接。夏南略一思忖，索性书就先不还了，后续看看店家什么反应再说。&lt;/p&gt;

&lt;p&gt;如今店家发短信来催促，夏南心中很是惭愧，决意去把书还了。看看时间，已是 23:03 了，得抓紧时间。&lt;/p&gt;

&lt;h3 id=&quot;part-6542c33f8a1&quot;&gt;梦深&lt;/h3&gt;

&lt;p&gt;恍惚间，夏南来到了一广场前，而怎么来的却想不起来。夏南怀疑自己是不是有些失忆，头有些昏沉、重胀，眼前这地儿似是来过，记忆却又模糊不清。他努力让心神镇定，看了看眼前的广场，用力回想着，记忆略略清晰了些。&lt;/p&gt;

&lt;p&gt;广场成丁字型，两侧都是商铺，要去的书店应该是在丁字交叉口左侧对面的一家店面。广场纵向的南面正是正门入口，夏南此时离入口处不远，正匆匆往里走去。&lt;/p&gt;

&lt;p&gt;广场上灯光有些昏暗，两侧建筑不高，都是西式风格，有点复古，略显陈旧，而大多店铺的门却又都是中式的。店铺几乎都还开着，看上去有古董店、服装店、宾馆、酒吧、饭馆等等，真真是应有尽有。人流高峰期，这里定特别繁华、热闹，人满为患。此时夜已渐深，广场上的人却还不少，有的人刚走进店铺，有的人正走出来，如是络绎不绝。奇怪的是，这广场静得出奇，人来人往，却没有发出一点声响。&lt;/p&gt;

&lt;p&gt;广场丁字交叉处有一水池，池正中有一立起的圆盘，盘上立一石龙，龙口向外吐水，水入石盘，盘中水满，西下溢出入池。夏南往前走着，流水声越来越清晰，渐渐的变得清脆，似乎这整个广场就只有这流水声。&lt;/p&gt;

&lt;p&gt;夏南拐入广场横向左侧，看着对面一家店铺似是曾借书的地方，但却怎么也看不清上面牌子上写着什么。他径直向店铺走去，推开门，喊道：“老板，我来还书。”里边走出一人，穿着灰色大褂，个子不高，却神采奕奕，左手负于身后，右手垂于胸前，道：“先生，您需要什么？”&lt;/p&gt;

&lt;p&gt;“我来还书。”&lt;/p&gt;

&lt;p&gt;“还书？”&lt;/p&gt;

&lt;p&gt;“是的。”&lt;/p&gt;

&lt;p&gt;“先生，您是不是走错了。我们这里只有字画，不曾有图书供借阅。”&lt;/p&gt;

&lt;p&gt;“我记得此处应是一书店，我曾于此借了一本书，借期至今日止，特来归还。”&lt;/p&gt;

&lt;p&gt;“您应该是记错了，本店于此已五载有余，不曾作过书店。”&lt;/p&gt;

&lt;p&gt;“是吗？”夏南顿时愣住了，突然才觉察到手中拿着的书。墨绿色硬壳书皮，书皮上没有书名，书看着有些陈旧，但却很干净。夏南拿起书，翻开扉页，正中浅浅地以篆书印着一个方形印章，夏南凑近仔细一看，印着“藏之高阁”四个字。其下还有一长型印，印有四字正楷“槐安书社”，还有一联系电话。夏南指着印章给字画店的店员看，“就是这个店，不是这儿吗？”&lt;/p&gt;

&lt;p&gt;“不是的！”字画店店员轻轻地摇了摇头。&lt;/p&gt;

&lt;p&gt;“抱歉，打扰了！”&lt;/p&gt;

&lt;p&gt;“没关系，您慢走！”&lt;/p&gt;

&lt;p&gt;夏南怔怔地走出店外，突然又模糊地记起，曾经借书的店员好像是一女子。也不知怎的，他顿时又来了些精神，向旁边的店铺走去。走进店里，里边甚是昏暗，看不出有什么，只看得出装潢是棕色木质风格。左侧有一柜台，柜台后是一女子，有些微胖，金色的短发垂于两颊，半遮着银色圆形大耳环，卷翘的睫毛下双眼很亮，紫莓色薄唇紧闭，穿一件黑色紧身皮衣。夏南走过去问道：“你好，请问你们这里是书店吗？”&lt;/p&gt;

&lt;p&gt;“不是！”&lt;/p&gt;

&lt;p&gt;“哦！”夏南刚进店时，看这儿的环境大概已知道结果，但问完仍觉有些失落。他又向店里看了看，这里应该是一个小酒馆，里面的人隐约可见，都举着杯，有说有笑。可仍然奇怪的是，店里寂静得很，夏南的耳朵就像塞了棉花一样，听不到一点声响。不过夏南没有细细推究，他大概一心只想着还书。夏南仍然打开书的扉页，指着上面的印章对女子说：“那这个书店你有见过吗？”&lt;/p&gt;

&lt;p&gt;“没有！”女子伸头看了看，仍是淡淡地答道。&lt;/p&gt;

&lt;p&gt;夏南又转向其他店铺询问，有的说没有见过这家书店，有的说好像在那个位置，可以去那边看看。慢慢地，夏南变得有些焦躁和急切，有些店员见他像是失了神一样，觉得他可能是受了什么刺激，也都很同情他，都耐心地回应着他的询问，有的甚至还安慰他：“没事，您慢慢找。”夏南感觉越来越累，最后似乎都听不清晰别人对他说的什么，只觉脑子嗡嗡作响，精神也接近奔溃。&lt;/p&gt;

&lt;p&gt;夏南几乎问遍了广场所有的店铺，仍未找到还书的书店，也未曾有人真真切切地告诉他见过这家书店。他拖着疲惫的身躯，走到广场纵向一侧的长椅上坐下，昂头看天，没有星星，夜幕灰蒙蒙的，极是压抑。他看了看时间，已经 23:51 了，想来这书今天是还不上了。自从来到这里，夏南就觉得神经一直是绷紧的，这极度消耗精神力，长此身体会很疲倦。他决定先镇定下心神，闭上眼，开始冥想。&lt;/p&gt;

&lt;h3 id=&quot;part-65432f7a645&quot;&gt;追悔&lt;/h3&gt;

&lt;p&gt;夏南发了疯似的想要找到借书的书店把书换上，是因为有些后悔前两天没有及时去把书换了，也为自己曾有不想还书的念头而感到羞愧。人往往总会因为一时纰谬的念头，而做了许多后悔的事，回头想要补救已不再有机会。&lt;/p&gt;

&lt;p&gt;小学毕业那天，夏南早早的就去了学校，为的是与同学们最后的玩耍。彼时，或许他还不太理解什么是分别，也不知自那天以后，与那些同学就再也不会有交集。等他到学校的时候，同学们已到了不少，早已在教室里、楼道间嬉戏、追逐、打闹，他也加入了进去。在夏南的同学中，有一个叫扬子都的，是他最好的朋友。子都的爸妈总是回家很晚，熟络之后，子都经常邀请夏南放学后去他家一起写作业。就这样，两人关系越来越好，最后可谓是孟不离焦。毕业那天，夏南和子都打闹到了学校的小树林里，见满地的松果，就捡松果互相砸了起来。砸着砸着，夏南发现自己面前已找不见松果，四处一扫视，发现地上有一小石子，可能是玩疯了，没及多想，捡起小石子就向子都砸去。此一砸，正中子都右脑。子都捂着头，像是很疼的样子，眼神中极是恨意地看向夏南。夏南的嬉笑逐渐收敛，虽觉内疚，但并未去询问子都的头怎么样，只抱歉地看着子都。子都看着生气极了，独自愤愤地跑回了教室。后来，老师来了，开会了，讲了些话。那天，老师具体说了些什么，夏南已经记不清了，他也没有注意听老师的讲话，只是时不时地关注着坐在前边离他略远处的子都。老师给大家发完毕业证后，就都各自回家了。子都走得尤其得快，夏南走在路上，一直没看到他的踪影。夏南闷闷不乐，觉得子都似乎有些小气了，就一小石子砸了他一下，怎么就不理自己了。小学毕业后，夏南因为家里的原因，转到其他城市上中学，此后再也没有见过子都。夏南每每想起此事，都觉得后悔，当初如果勇敢向前一步，向子都道歉，或许后来即使天南海北，他们仍是最好的朋友。&lt;/p&gt;

&lt;p&gt;上初中的时候，夏南去图书馆借了一本书，不久因为某些原因，图书馆不再开放，后来图书馆就一直锁着，没人管理。图书管关闭后也没人管之前借出去的书有没有还，夏南也一直没有把那本书还回去，至今都还在老家的书柜里。每次回家看到那本书，夏南都有点愧疚之意，虽然书没还回去学校一直没追究，但它毕竟不真正属于自己。&lt;/p&gt;

&lt;p&gt;夏南回想着过去这些事，不禁感叹，何时才能不为一时之念，而促成后悔之事呢？&lt;/p&gt;

&lt;h3 id=&quot;part-6542a099e35&quot;&gt;契阔&lt;/h3&gt;

&lt;p&gt;“夏！”&lt;/p&gt;

&lt;p&gt;夏南一惊，这声音太熟悉了，即使多年过去，也无法从记忆里抹去。夏南抬头望去，在他左前方，一位姑娘正嫣然浅笑着看着他。&lt;/p&gt;

&lt;p&gt;“盈盈！”&lt;/p&gt;

&lt;p&gt;与曾经相比，盈盈稍纤瘦了些。她穿着一双粉色浅口低跟皮鞋，鞋面有一蝴蝶结，一袭浅白色长裙直垂至腿部，裙色似又泛着淡红，轻风缓缓拂过，裙摆也随之微微曳动，在微弱的灯光照耀下，略有点点银光闪烁。盈盈迈着莲步，向夏南走来，也在长椅上坐下。&lt;/p&gt;

&lt;p&gt;“我在前面的少儿培训机构上班，今天老师们在一起讨论教案内容，有些争议，所以下班晚了。”&lt;/p&gt;

&lt;p&gt;夏南侧头看向盈盈，盈盈也正向他看来。与曾经的活泼灵动相比，盈盈多了几分端庄，下巴上的痣不见了，带着一条金色项链，吊坠是简单的菱形形状。四目相对，盈盈似有些矜持，又一浅笑，只一刹那，便避开了夏南的目光。此后便是长长的沉默，这不禁让人想起拜伦的诗：“假使我又见你，隔了悠长的岁月，我如何致意，以沉默？以眼泪？”&lt;/p&gt;

&lt;p&gt;“你......你，怎么样？”夏南还是先开了口。&lt;/p&gt;

&lt;p&gt;“我吗？”盈盈一笑。&lt;/p&gt;

&lt;p&gt;“嗯！”&lt;/p&gt;

&lt;p&gt;“我结婚了！”&lt;/p&gt;

&lt;p&gt;“又离婚了！”盈盈低下头，又补了一句。&lt;/p&gt;

&lt;h3 id=&quot;part-6542a1371a0&quot;&gt;如梦&lt;/h3&gt;

&lt;p&gt;“那时，我本来打算去你家找你，可想想又觉得自己不够好，怕照顾不好你，觉得你值得更好的，于是便没了勇气。”&lt;/p&gt;

&lt;p&gt;“想想过去，就像是一场梦，如今也不确定自己是不是醒来了。”&lt;/p&gt;

&lt;p&gt;“浮生若梦！”&lt;/p&gt;

&lt;p&gt;“历经种种，细细想来，人生悲欢离合，聚聚散散，都像是既定的命数，每个人都有每个人的命，又何必为此多多伤怀。”&lt;/p&gt;

&lt;p&gt;“谁曾想三年异地都熬过去了，最终却敌不过现实。”&lt;/p&gt;

&lt;p&gt;“彼时年轻，都是一时意气。哈哈，当初你就不该叫我盈盈。”&lt;/p&gt;

&lt;p&gt;“是啊，当初就不该叫你盈盈！”&lt;/p&gt;

&lt;h3 id=&quot;part-65432f7a9d3&quot;&gt;追忆&lt;/h3&gt;

&lt;p&gt;“夏南哥哥，你在做什么呢？”&lt;/p&gt;

&lt;p&gt;“我在实验室呢，还在做实验！”&lt;/p&gt;

&lt;p&gt;“你一整天都没理我了！”&lt;/p&gt;

&lt;p&gt;“我这不忙着写论文嘛，导师催得紧，他不让我毕业可咋办！”&lt;/p&gt;

&lt;p&gt;“可是，你一整天都不理我，委屈！”&lt;/p&gt;

&lt;p&gt;“好了，你要乖乖的嘛，我一毕业就去找你啦！”&lt;/p&gt;

&lt;p&gt;“你给我起个昵称吧，以后我不想你直接叫我名字。”&lt;/p&gt;

&lt;p&gt;“嗯......那就叫盈盈吧！”&lt;/p&gt;

&lt;p&gt;“盈盈？为什么叫盈盈呢？”&lt;/p&gt;

&lt;p&gt;“因为盈盈好听啊！”&lt;/p&gt;

&lt;p&gt;“就因为好听？”&lt;/p&gt;

&lt;p&gt;“盈盈一水间，脉脉不得语。”&lt;/p&gt;

&lt;p&gt;“这也太感伤了！”&lt;/p&gt;

&lt;p&gt;“那谁让你离我这么远呢！咱们现在何止是一水相间，中间可是横着黄河和长江呢。”&lt;/p&gt;

&lt;p&gt;“哼，我不管！换掉，换掉，换掉！”&lt;/p&gt;

&lt;p&gt;“七夕我就去找你了！”&lt;/p&gt;

&lt;h3 id=&quot;part-65427d66215&quot;&gt;再别&lt;/h3&gt;

&lt;p&gt;“我该走了，太晚了！”盈盈起身，准备走。&lt;/p&gt;

&lt;p&gt;“我送你吧！”&lt;/p&gt;

&lt;p&gt;“不用，我住得离这儿不远。”&lt;/p&gt;

&lt;p&gt;夏南略一忸怩，盈盈已走出去了十多步。夏南说出了曾经没有说，也一直还没机会说的两个字，“珍重”。&lt;/p&gt;

&lt;p&gt;盈盈止住了脚步，却没有回头，仰头似在看天。须臾，盈盈浅浅低语：“于嗟阔兮，不我活兮。于嗟洵兮，不我信兮。”这声虽轻，但似乎整个广场都能听见，像是被放大了似的，萦绕在夏南耳边。夏南顿时像是被拉进了无尽的回忆之中，眼前一片迷离，脑中却是无数画面闪过。&lt;/p&gt;

&lt;p&gt;夏南回过神时，发现盈盈早已不见踪影。在这茫茫夜色之下，仍是人来人往，但也仍然静得出奇。&lt;/p&gt;

&lt;p&gt;夏南再也忍不住胸中激荡，不自觉已昂头长大了嘴，一腔积郁喷泻而出，滚泪直下。夏南这一大哭，却没有发出哭声，或许是因为这伤心的程度已经达到了声带所能表达的极限。片刻后，才从夏南嘴里传出一声号啕，持续良久，响彻夜幕。渐渐地，夏南应是已没了力气，哭声渐低。夏南尝试收摄这失控的情绪，只觉脸上肌肉被撑得巨疼，胸口像是压着巨石，有些喘不过气。夏南缓缓长舒一口气，又用双手戳了戳脸，心绪似缓解了一些。&lt;/p&gt;

&lt;p&gt;突然，夏南意识到手中的书不见了！&lt;/p&gt;

&lt;h3 id=&quot;part-6542c33fef4&quot;&gt;梦醒&lt;/h3&gt;

&lt;p&gt;滴答答滴答铛铛铛，滴答答滴答铛铛铛......&lt;/p&gt;

&lt;p&gt;夏南被惊醒，猛一睁眼，一时不知所措，像是有些魔怔。过了许久才缓过神来，他看了看表，23:30，原来刚刚响的是十一点半的闹钟。为了提醒自己不要熬夜，夏南定了晚上十一点半的闹钟，要求自己尽量要在十二点之前睡。由于今天实在太困了，不到十点就躺床上睡着了。&lt;/p&gt;

&lt;p&gt;夏南只觉心口阵阵锥痛，起来坐在椅子上，想要平复下心绪再睡。这时他才发现，因为睡得早，窗帘都还没拉上。窗外看去，白玉般的圆月已斜向西面，这应该又是月中了。夏南心里不觉想着：我这是在梦里，还是醒来了。&lt;/p&gt;

&lt;!-- 本文旨在表达对往事的追悔，想要去偿还，去补偿，却已不再有机会。 --&gt;
</description>
        <pubDate>Sun, 17 Apr 2022 00:00:00 +0800</pubDate>
        <link>https://donothing.site/2022/04/17/return-the-book/</link>
        <guid isPermaLink="true">https://donothing.site/2022/04/17/return-the-book/</guid>
        
        <category>西窗梦集</category>
        
        
        <category>西窗梦集</category>
        
      </item>
    
      <item>
        <title>孤独</title>
        <description>&lt;p&gt;&lt;strong&gt;【导读】&lt;/strong&gt; &lt;em&gt;维摩诘说，“从痴有爱，则我病生”，人因为有痴，有爱，所以才会生病。痴与爱耗费心神，损伤身心，以致病起。但我觉得，人于万物的区别正是因为痴和爱，人生的意义及有趣之处也在于有痴有爱。这和周国平说，“孤独源于爱，无爱的人不会孤独”，有异曲同工之处。因为有爱，内心才有温度，才会怜悯众生，才会感到孤独。孤独有时反而让人感觉充实。“孤独和喧嚣都难以忍受”，这又像村上春树说的，“看海看久了想见人，见人见多了想看海”。有时候，希望独处，这是在积蓄力量；有时候又渴望喧闹，这是需要释放。&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://static.donothing.site/xlwb/imgs/wx2/mw2000/c3c88275gy1gr8ghrsn8sj21910pbtat.jpg&quot; alt=&quot;看海&quot;&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;摘自 周国平《人与永恒》&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;孤独源于爱，无爱的人不会孤独。&lt;/p&gt;

&lt;p&gt;也许孤独是爱的最意味深长的赠品，受此赠礼的人从此学会了爱自己，也学会了理解别的孤独的灵魂和深藏于它们之中的深邃的爱。从而为自己建立了一个珍贵的精神世界。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;孤独是人的宿命，它基于这样一个事实：我们每个人都是这世界上一个旋生旋灭的偶然存在，从无中来，又要回到无中去，没有任何人任何事情能够改变我们的这个命运。是的，甚至连爱也不能。凡是领悟人生这样一种根本性孤独的人，便已经站到了一切人间欢爱的上方，爱得最热烈时也不会做爱的奴隶。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;和别人混在一起时，我向往孤独。孤独时，我又向往看到我的同类。但解除孤独毕竟只能靠相爱相知的人，其余的人扰乱了孤独，反而使人更感孤独，犹如一种官能，因为受到刺激而更加意识到自己的存在。&lt;/p&gt;

&lt;p&gt;孤独和喧嚣都难以忍受。如果一定要忍受，我宁可选择孤独。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;每逢节日，独自在灯下，心中就有一种非常浓郁的寂寞，浓郁得无可排遣，自斟自饮生命的酒，别有一番酩酊。&lt;/p&gt;

&lt;p&gt;人生作为过程总要逝去，似乎哪种活法都一个样。但就是不一样。我需要一种内在的沉静，可以以逸待劳地接收和整理一切外来印象。这样，我才觉得自己具有一种连续性和完整性。当我被过于纷繁的外部生活搅得不复安宁时，我就断裂了，破碎了，因而也就失去了吸收消化外来印象的能力。&lt;/p&gt;

&lt;p&gt;世界是我的食物。人只用少量时间进食，大部分时间在消化。独处就是我消化世界。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;在静与闹、孤独与合群之间，必有一个适合于我的比例或节奏。如果比例失调，节奏紊乱，我就会生病--太静则抑郁，太闹则烦躁。抑郁使我成为诗人，烦躁使我成为庸人。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;一个精神上自足的人是不会羡慕别人的好运气的，尤其不羡慕低能儿的好运气。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;活动和沉思，哪一种生活更好?&lt;/p&gt;

&lt;p&gt;有时候，我渴望活动,漫游，交往，恋爱,冒险,成功。如果没有充分尝试生命的种种可能性就离开人世，未免太遗憾了。但是,我知道，我的天性更适合于过沉思的生活。我必须休养我的这颗自足的心灵，唯有带着这颗心灵去活动，我才心安理得并且确有收获。&lt;/p&gt;

&lt;p&gt;如果没有好胃口，天天吃宴席有什么乐趣?如果没有好的感受力，频频周游世界有什么意思?反之，天天吃宴席的入怎么会有好胃口，频频周游世界的人怎么会有好的感受力?&lt;/p&gt;

&lt;p&gt;心灵和胃一样，需要休息和复原。独处和沉思便是心灵的休养方式。当心灵因充分休息而饱满，又因久不活动而饥渴时，它就能最敏锐地品味新的印象。&lt;/p&gt;

&lt;p&gt;所以，问题不在于两者择一。高质量的活动和高质量的宁静都需要，而后者实为前者的前提。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;外倾性格的人容易得到很多朋友，但真朋友总是很少的。内倾者孤独，一旦获得朋友，往往是真的。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;健谈者往往耐不得寂寞，因为他需要听众。寡言者也需要听众，但这听众多半是他自己，所以他比较安于独处。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;有的人只有在沸腾的交往中才能辨认他的自我。有的人却只有在宁静的独处中才能辨认他的白我。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;11&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;没有自己独居的处所是多么可怕的事，一切都暴露无遗了。在群居中，人不得不掩饰和压抑自己的个性。在别人目光的注视下，谁还能坐在那里恬然沉思，捕捉和记录自己的细微感受。住宅危机导致了诗和哲学的生态危机。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;12&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;学会孤独，学会与自己交谈，听自己说话，--就这样去学会深刻。当然前提是：如果孤独是可以学会的话。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;13&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;获得理解是人生的巨大欢乐。然而，一个孜孜以求理解、没有旁人的理解便痛不欲生的人却是个可怜虫。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;14&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;被人理解是幸运的，但不被理解未必就是不幸。一个把自己的价值完全寄托于他人的理解上面的人往往并无价值。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;人与人之间的理解或不理解是命运，误会却是命运的捉弄。我坦然接受命运，但为命运的捉弄悲戚。&lt;/p&gt;

&lt;p&gt;可是，何必表白呢?表白是理解的死亡证书。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;16&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;知道痛苦的价值的人，不会轻易向别人泄露和展示自己的痛苦，哪怕是最亲近的人。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;17&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;一个特立独行的人而又不陷于孤独，这怎么可能呢?然而，尽管注定孤独，仍然会感觉到孤独的可怕和难以忍受。上帝给了他一颗与众不同的灵魂，却又赋予他与普通人一样的对于人间温暖的需要，这正是悲剧性之所在。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;18&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;说到底，在这世界上，谁的经历不是平凡而又平凡的?心灵历程的悬殊才在人与人之间铺下了鸿沟。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;19&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;无聊、寂寞、孤独是三种不同的心境。&lt;/p&gt;

&lt;p&gt;无聊是把自我消散于他人之中的欲望，它寻求的是消遣。寂寞是自我与他人共在的欲望，它寻求的是普通的人间温暖。孤独是把他人接纳到自我之中的欲望，它寻求的是理解。&lt;/p&gt;

&lt;p&gt;无聊者自厌，寂寞者自怜，孤独者自足。&lt;/p&gt;

&lt;p&gt;庸人无聊，天才孤独，人人都有寂寞的时光。&lt;/p&gt;

&lt;p&gt;无聊是喜剧性的，孤独是悲剧性的，寂寞是中性的。&lt;/p&gt;

&lt;p&gt;无聊属于生物性的人，寂寞属于社会性的人，孤独属于形而上的人。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;心灵的孤独与性格的孤僻是两回事。孤僻属于弱者，孤独属于强者。两者都不合群，但前者是因为惧怕受到伤害，后者是因为精神上的超群卓绝。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;21&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;寂寞是决定人的命运的情境。一个人忍受不了寂寞，就寻求方便的排遣办法，去会朋友，谈天，打牌，看电视，他于是成为一个庸人。靠内心的力量战胜寂寞的人，必是诗人和哲学家。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;22&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;老是听别人发表同样的见解和感叹，我会感到乏味。不过我知道，在别人眼里我也许更乏味，他们从我这里甚至连见解和感叹也听不到，我不愿重复，又拿不出新的，于是只把沉默给他们。与人共享沉默未免太古怪，所以，我躲了起来……&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;23&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;我天性不宜交际。在多数场合，我不是觉得对方乏味，就是害怕对方觉得我乏味。可是我既不愿忍受对方的乏味，也不愿费劲使自己显得有趣，那都太累了。我独处时最轻松，因为我不觉得自己乏味，即使乏味，也自己承受，不累及他人，无需感到不安。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;24&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;一切交往都有不可超越的最后界限。在两个人之间，这种界限是不清晰的，然而又是确定的。一切麻烦和冲突都起于无意中想突破这个界限。但是，一旦这个界限清晰可辨并且严加遵守，那么，交往的全部魅力就丧失了，从此情感退场，理智维持着秩序。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;在任何两人的交往中，必有一个适合于彼此契合程度的理想距离，越过这个距离，就会引起相斥和反感。这一点既适用于爱情，也适用于友谊。&lt;/p&gt;

&lt;p&gt;也许，两个人之间的外在距离稍稍大于他们的内在距离，能使他们之间情感上的吸引力达到最佳效果。形式应当稍稍落后于内容。实际上并非心心相印的人，倘若形影不离，难免会互相讨厌。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;26&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;爱可以抚慰孤独，却不能也不该消除孤独。如果爱妄图消除孤独，就会失去分寸，走向反面。&lt;/p&gt;

&lt;p&gt;分寸感是成熟的爱的标志，它懂得遵守人与人之间必要的距离，这个距离意味着对于对方作为独立人格的尊重，包括尊重对方独处的权利。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;27&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;这是一个孤独的人。有一天，世上许多孤独的人发现了他的孤独，于是争着要同他交朋友。他困惑了：他们因为我的孤独而深信我是他们的朋友，我有了这么多朋友，就不再孤独，如何还有资格做他们的朋友呢?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;28&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;你们围着他，向他喝彩，他惶恐不安了。你们哪里知道他心中的自卑，他的成就只是做出来给自己看的，绝没有料到会惊动你们。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;29&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&amp;quot;假如把你放逐到火星上去，只有你一个人，水远不能再回地球接触人类，同时让你长生不老，那时你做什么?&amp;quot;&lt;/p&gt;

&lt;p&gt;&amp;quot;写作。&amp;quot;&lt;/p&gt;

&lt;p&gt;&amp;quot;假如你的作品永远没有被人读到的希望?&amp;quot;&lt;/p&gt;

&lt;p&gt;&amp;quot;自杀。&amp;quot;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;我相信，一颗优秀的灵魂，即使永远孤独，永远无人理解，也仍然能从自身的充实中得到一种满足，它在一定意义上是自足的。但是，前提是人类和人类精神的存在，人类精神的基本价值得到肯定。唯有置身于人类中，你才能坚持对于人类精神价值的信念，从而有精神上的充实自足。优秀灵魂的自爱其实源于对人类精神的泛爱。如果与人类精神永远隔绝，譬如说沦入无人地带或哪怕是野蛮部落之中，永无生还的希望，思想和作品也永无传回人间的可能，那么，再优秀的灵魂恐怕也难以自足了。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;31&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;孤独者必不合时宜。然而，一切都可以成为时髦，包括孤独。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;32&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;语言是存在的家。沉默是语言的家。饶舌者扼杀沉默，败坏语言，犯下了双重罪过。&lt;/p&gt;
</description>
        <pubDate>Sun, 16 Jan 2022 00:00:00 +0800</pubDate>
        <link>https://donothing.site/2022/01/16/alone/</link>
        <guid isPermaLink="true">https://donothing.site/2022/01/16/alone/</guid>
        
        <category>美文</category>
        
        
        <category>美文收录</category>
        
      </item>
    
      <item>
        <title>C/C++ 札记：第一个 C++ 程序</title>
        <description>&lt;p&gt;C++ 是一种静态类型，编译型，强类型，通用的编程语言，支持面向过程和面向对象编程。C++ 是 C 的超集，是在 C 语言的基础上进一步扩充和完善，几乎任何合法的 C 程序都是合法的 C++ 程序。&lt;/p&gt;

&lt;p&gt;第一个 C++ 程序：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * 第一个 C++ 程序
 */&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/* 引入头文件 */&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;iostream&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* 引入名字空间 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/* 程序的入口函数 */&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 定义变量，并赋值&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 向标准流输出数据&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 返回一个 int 类型的数据，用于表示程序的退出状态&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;可将以上代码保存在 hello.cpp 中，以编译运行程序。C++ 程序文件的后缀名通常用 &lt;code&gt;.cpp&lt;/code&gt;、&lt;code&gt;.cc&lt;/code&gt; 或者 &lt;code&gt;.cxx&lt;/code&gt;。&lt;/p&gt;

&lt;h3 id=&quot;part-6542d68b860&quot;&gt;注释&lt;/h3&gt;

&lt;p&gt;注释是解释性语句，不影响程序的逻辑，但能提高源代码的可读性，注释中的所有字符会被编译器忽略。&lt;/p&gt;

&lt;p&gt;C++ 支持单行注释和多行注释。多行注释以 &lt;code&gt;/*&lt;/code&gt; 开始，以 &lt;code&gt;*/&lt;/code&gt; 结束。单行注释以 &lt;code&gt;//&lt;/code&gt; 开始，直至行尾结束。多行注释也可以作为单行注释用。&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/* 多行注释示例
第二行
第三行
*/&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 单行注释&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/* 作为单行注释的多行注释 */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;part-3786ce1c2f77e7a&quot;&gt;头文件&lt;/h3&gt;

&lt;p&gt;在编写 C++ 程序时，通常需要引入外部库（包括标准库和第三方库），这些外部库通常都以头文件和动态库或者静态库的新式提供。在 C++ 中，头文件也是一种源代码的形式，但头文件不用被编译。头文件主要提供全局变量、全局函数的声明或公用数据类型的定义，其作用主要是实现分离编译和代码复用。当需要外部的某些声明或者定义时，就可以将相应的头文件引入。引入头文件使用 &lt;code&gt;#include&lt;/code&gt; 宏命令，宏会在编译器预处理阶段进行展开，&lt;code&gt;#include&lt;/code&gt; 的作用就是把指定的文件的内容插入其所在位置处。&lt;/p&gt;

&lt;p&gt;C++ 标准库的头文件通常不带 &lt;code&gt;.h&lt;/code&gt; 后缀，这主要是为了与旧版或者 C 语言的头文件做区分，C++ 标准库的头文件通常可以在 &lt;strong&gt;/usr/include/c++&lt;/strong&gt; 中找到。&lt;/p&gt;

&lt;p&gt;如 &lt;code&gt;iostream&lt;/code&gt; 便是标准库中的头文件，其申明了 std::cout 和 std::endl 等变量。&lt;strong&gt;std::cout&lt;/strong&gt; 表示输出到标准输出，&lt;strong&gt;std:endl&lt;/strong&gt; 表示换行。&lt;/p&gt;

&lt;h3 id=&quot;part-2bc6d0434d052e78&quot;&gt;命名空间&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;命名空间（namespace）&lt;/code&gt; 主要用于区分不同库中相同名称的函数、类、变量等。使用了命名空间即定义了上下文。本质上，命名空间就是定义了一个范围。命名空间的声明使用 &lt;code&gt;namespace&lt;/code&gt; 关键字，如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;使用名字空间需要使用 &lt;code&gt;::&lt;/code&gt; 域解析符，也叫做作用域操作符。如 &lt;code&gt;a::c&lt;/code&gt;，&lt;code&gt;b::c&lt;/code&gt;，对于没有声明名字空间的全局空间，称为无名名字空间，访问时不需要指定域解析符，也可以用类似 &lt;code&gt;::c&lt;/code&gt; 的方式访问。&lt;/p&gt;

&lt;p&gt;此外，还可以使用 &lt;code&gt;using&lt;/code&gt; 关键字来引入名字空间。使用 using 时，可以引入名字空间中的单个标识符，也可以全部引入。如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// 仅引入名字空间 std 中的 string, cout, endl&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 引入名字空间 std 中的所有内容&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这样声明之后，就如示例程序中一样，string、 cout、 endl 前面的 std:: 就可以省略不写了。但需要注意的是，虽然可以省略不写，但 string 变量的全名仍然是 std::string，如果有一个全局变量也叫 string，其与 std::string 应该是两个不同的变量。所以，为了区分，全局变量的 string 可以写作 ::string（如果 string 是函数，::string 引用的是无名名字空间中的 string，而如果是变量，则有无 :: 都为冲突）。&lt;/p&gt;

&lt;p&gt;名字空间还可以嵌套，如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;part-65427f6bd63&quot;&gt;分号&lt;/h3&gt;

&lt;p&gt;在 C++ 中，分号(;) 是一个语句结束符。每个语句必须以分号结束。也表明一个逻辑实体的结束。&lt;/p&gt;

&lt;p&gt;在有些编程语言中，会以 换行符(\n) 作为结束符的标识。由于 c++ 不以换行符结束，所以可以在一行内放置多个语句，但是为了便于阅读，除非是某些特殊情况，通常都只在一行实现一个语句。&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// 合法的语句&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;part-3786c796ecdf888&quot;&gt;代码块&lt;/h3&gt;

&lt;p&gt;代码块是一组使用 大括号({}) 括起来的按物理逻辑连接的语句，也称为复合语句（compound statement）。一个代码块也标记着一个变量作用域。即在一个代码块中定义的变量，只在该代码块中有效。&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello world&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// 此处的 s 未定义，会报错&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;part-2da2d90c35afe693&quot;&gt;程序入口&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;main()&lt;/code&gt; 函数是 C/C++ 程序的入口函数，所谓入口函数，是指程序从这里开始。实际上一个 C/C++ 程序也只执行 main 函数里的逻辑。一个 C/C++ 程序可以包含若干函数，但至少必须包含 main 函数。C/C++ 标准规定 main 函数的返回值类型为 int，返回值用于表示程序的退出状态，返回 0 表示程序正常退出，返回非 0，表示出现异常。C/C++ 标准规定，main 函数原型有两种：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/* 无参数形式 */&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/* 带参数形式 */&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;int&lt;/code&gt; 指明了 main() 函数的返回值类型，函数名后面的圆括号一般包含传递给函数的信息。&lt;code&gt;void&lt;/code&gt; 表示没有给函数传递参数。&lt;/p&gt;

&lt;h3 id=&quot;part-6542802d2b9&quot;&gt;函数&lt;/h3&gt;

&lt;p&gt;函数是执行某种操作的代码块。函数的定义需提供函数名称、返回值类型、参数列表，以及函数主体。函数定义的一般形式如下：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;return_type&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parameter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;返回值类型：&lt;/strong&gt; 定义函数是必须指定返回值类型，如 int、float、string 等。如果函数不需要返回值，则可以将返回值指定为 void，即表明函数不返回任何值&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;函数名称：&lt;/strong&gt; 为函数指定一个标识符，以便于后续用该名称使用函数。函数名和参数列表一起构成了函数签名&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;参数：&lt;/strong&gt; 参数就像是占位符。当函数被调用时，向参数传递一个值，这个值被称为实际参数。函数定义时指定的参数列表被称为形式参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的，也就是说，函数可以不包含参数&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;函数主体：&lt;/strong&gt; 函数主体包含一组定义函数执行任务的语句，即描述函数要完成的功能&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;一个好的编程习惯是，将不同的逻辑任务划分到不同的函数中，依次来更好的组织，是代码逻辑清晰，更易读。&lt;/p&gt;

&lt;h3 id=&quot;part-2bd51736d5b3b9b&quot;&gt;变量与类型&lt;/h3&gt;

&lt;p&gt;示例中的 &lt;em&gt;string s = &amp;quot;hello world&amp;quot;;&lt;/em&gt; 表示定义 string 类型的变量，变量名为 s，值为 hello world。&lt;strong&gt;变量是标记内存区域的一个名称&lt;/strong&gt;。定义变量 s 时，&amp;quot;hello world&amp;quot; 文件字符串被存放在内存中，s 则标记了这块内存的位置，访问 s 时则可以取出这块内存的内容。变量 s 是一个标识符，用于标记变量。&lt;/p&gt;

&lt;p&gt;C++ &lt;strong&gt;标识符&lt;/strong&gt; 是用于标识变量，函数，类，模块或任何其他用户定义项的名称。标识符以字母 A 到 Z 或 a 到 z 或下划线 &lt;code&gt;_&lt;/code&gt;开头，后跟零个或多个字母，下划线和数字（0到9）。C++ 对大小写敏感，即 A 和 a 是两个不同的标识符。&lt;/p&gt;

&lt;p&gt;C++ 是强类型的语言，所以定义变量是必须指定变量的类型，类型决定了变量存储的大小和布局。C++ 中常见的变量类型有 char, bool, int, float, double 等。&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.01&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;布尔类型（bool）相较于 C 语言是 C++ 中新增的类型，布尔值包括 true 或 false。如果布尔变量用于算术表达式中，将被隐式转换成 int 类型，true 为 1，false 为 0。&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cond&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cond&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cond&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// output 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;此外，C++ 还包括 枚举、指针、数组、引用、数据结构、类等类型。&lt;/p&gt;

&lt;h3 id=&quot;part-3786df3fb0ad100&quot;&gt;标准流&lt;/h3&gt;

&lt;p&gt;示例中的 &lt;em&gt;cout &amp;lt;&amp;lt; s &amp;lt;&amp;lt; endl;&lt;/em&gt; 表示将变量 s 的内容输出到标准输出流中。标准流是一种 &lt;strong&gt;输入/输出功能&lt;/strong&gt;，包括标准输入流、标准输出流和标准错误流。标准输入流连接输入设备，如键盘；标准输出流和标准错误流连接输出设备，如显示器、打印机等。&lt;/p&gt;

&lt;p&gt;C++ 在 &lt;code&gt;iostream&lt;/code&gt; 头文件中定义了 cin、cout、cerr 和 clog 对象，分别对应于标准输入流、标准输出流、非缓冲标准错误流和缓冲标准错误流。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; 本来是移位运算符，在这里被 overload 成了输出函数。&lt;/p&gt;

&lt;p&gt;示例类似如下一样 C 语言程序：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello world!&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;part-2e11800aa9058512&quot;&gt;编译运行&lt;/h3&gt;

&lt;p&gt;编译 C++ 程序需要使用 g++ 编译器。最简单的编译方式：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;g++ hello.cpp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;编译时编译器默认将编译结果输出到 a.out 可执行文件中，可以直接运行该文件：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./a.out
Hello world!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;也使用 -o 选项指定输出的可执行程序的文件名。如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;g++ hello.cpp &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; hello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;如果有多个源文件，可以用如下的方式编译：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;g++ test1.cpp test2.cpp &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;在 unix 系统环境下，对于一些简单的测试代码，可以编写一个脚本来实现一键编译运行，如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;========= Compile:&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~ &lt;span class=&quot;s2&quot;&gt;&quot;.cpp&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;g++ -Wall -std=c++11&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Darwin&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CC&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -stdlib=libc++&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fi
else
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;gcc -Wall&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TMPDIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dirname&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mktemp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;OUTFILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TMPDIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/cplus-tmp-out&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$OUTFILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    /bin/rm &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$OUTFILE&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$CC&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$OUTFILE&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 0 &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;========= Run:&quot;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$OUTFILE&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi

if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$OUTFILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    /bin/rm &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$OUTFILE&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;如果程序比较简单，也可以尝试使用 &lt;a href=&quot;https://root.cern/cling/&quot;&gt;cling&lt;/a&gt;，其是一个交互式的 C++ 解析器，基于 LLVM 和 C++ 的前端 clang。可以直接运行 cling 来测试简单的语法逻辑，如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cling

&lt;span class=&quot;k&quot;&gt;******************&lt;/span&gt; CLING &lt;span class=&quot;k&quot;&gt;******************&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; Type C++ code and press enter to run it &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;             Type .q to &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;             &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*******************************************&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;cling]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;int a &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;cling]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;a
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;int&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 1
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;cling]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;int b &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 2&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;cling]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;b
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;int&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 2
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;cling]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;a + b
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;int&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;也可以用 cling 直接运行一个文件：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;hello.cpp | cling &lt;span class=&quot;nt&quot;&gt;--nologo&lt;/span&gt;
Hello World
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;可以编写一个 shell function 来自动的判断是需要直接运行解释器，还是需要运行一个文件：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;kling&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; | cling &lt;span class=&quot;nt&quot;&gt;--nologo&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else
        &lt;/span&gt;cling &lt;span class=&quot;nv&quot;&gt;$*&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;part-2bb23717ee7e9bfc&quot;&gt;参考资料&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.runoob.com/cplusplus/&quot;&gt;https://www.runoob.com/cplusplus/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://iowiki.com/cplusplus/cpp_quick_guide.html&quot;&gt;https://iowiki.com/cplusplus/cpp_quick_guide.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/zh-cn/cpp/cpp/&quot;&gt;https://docs.microsoft.com/zh-cn/cpp/cpp/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 02 Jan 2022 00:00:00 +0800</pubDate>
        <link>https://donothing.site/2022/01/02/cpp-hello/</link>
        <guid isPermaLink="true">https://donothing.site/2022/01/02/cpp-hello/</guid>
        
        <category>C/C++</category>
        
        
        <category>C/C++</category>
        
      </item>
    
      <item>
        <title>Pip 使用简易指南</title>
        <description>&lt;p&gt;&lt;code&gt;pip&lt;/code&gt; 是 Python 的包管理工具，用于第三方库的查找、下载、安装、卸载等。&lt;/p&gt;

&lt;p&gt;从 Python 3.4 开始，pip 默认包含在 Python 二进制安装程序中。如果安装的 Python 版本里没有自带 pip 工具，可以通过下载 &lt;a href=&quot;https://bootstrap.pypa.io/get-pip.py&quot;&gt;get-pip.py&lt;/a&gt; 文件，然后通过如下方式安装:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;python get-pip.py &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;pip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;运行 pip 可以通过 &lt;code&gt;pip&lt;/code&gt; 命令，也可以用 &lt;code&gt;python -m pip&lt;/code&gt; 来完成：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pip &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
pip 21.3.1 from /usr/local/lib/python3.8/dist-packages/pip &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;python 3.8&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; pip &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
pip 21.3.1 from /usr/local/lib/python3.8/dist-packages/pip &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;python 3.8&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/bin/python3 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; pip &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
pip 21.3.1 from /usr/local/lib/python3.8/dist-packages/pip &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;python 3.8&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;使用 &lt;code&gt;/bin/python3 -m pip&lt;/code&gt; 这样的方式运行 pip 是比较推荐的方式，因为在你的系统里可能存在多个 Python 环境，这样运行可以显式的指示为哪个环境使用 pip。pip 命令的语法格式为：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;python &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; pip &amp;lt;&lt;span class=&quot;nb&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;options]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;一些常用的公共的参数：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;--debug  启动 DEBUG 模式
-v, --verbose  显示更加详细的
-q, --quiet  显示更少的信息
--log &amp;lt;path&amp;gt;  将输出记录到文件
--proxy &amp;lt;proxy&amp;gt;  指定代理服务器，格式为 [user:passwd@]proxy.server:port
--retries &amp;lt;retries&amp;gt;  指定最大的尝试次数，默认为 5 次
--timeout &amp;lt;sec&amp;gt;  指定超时时间，默认为 15 秒
--cache-dir &amp;lt;dir&amp;gt;  指定缓存目录
--no-cache-dir  禁用缓存
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;install&quot;&gt;Install&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;pip&lt;/code&gt; 默认从 &lt;a href=&quot;https://pypi.org/&quot;&gt;PyPI&lt;/a&gt; 下载包并安装，其基本用法为：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;options] &amp;lt;requirement specifier&amp;gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;package-index-options] ...
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;options] &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &amp;lt;requirements file&amp;gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;package-index-options] ...
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;options] &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &amp;lt;vcs project url&amp;gt; ...
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;options] &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &amp;lt;&lt;span class=&quot;nb&quot;&gt;local &lt;/span&gt;project path&amp;gt; ...
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;options] &amp;lt;archive url/path&amp;gt; ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;从 PyPI 下载包时，pip 使用 &lt;a href=&quot;https://pypi.org/simple/&quot;&gt;HTTP simple interface&lt;/a&gt; 查找相应的包。除了从 PyPI 下载包安装外，pip 还支持从本地文件、本地项目目录、压缩包、远程路径（url）安装。&lt;/p&gt;

&lt;p&gt;安装包时的常用参数：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;-r, --requirement &amp;lt;file&amp;gt;  指定依赖说明文件
--no-deps  不安装依赖
--pre  包含预发布版本或开发测试版本，默认只搜索稳定版
-e, --editable &amp;lt;path/url&amp;gt;  以可编辑模式安装，通常用于开发调试本地项目
--user  安装到用户目录下，通常为 ~/.local/
-U, --upgrade  升级指定的包及其依赖
--force-reinstall  强制重装指定包
-I, --ignore-installed  忽略已经安装的包
-i, --index-url &amp;lt;url&amp;gt;  指定包仓库的索引地址，即所谓的源，默认为 https://pypi.org/simple
--extra-index-url  额外的包仓库索引地址
--no-index  忽略包仓库地址（通常与 --find-links 配合使用，实现离线安装）
--find-links  指定查找路径，可以是一个本地路径，或者一个 HTML 文件链接
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;pip&lt;/code&gt; 支持从 &lt;strong&gt;版本控制系统 VCS&lt;/strong&gt;（version control systems）安装包，这种支持需要系统中存在相应 VCS 的可执行文件，且需要在 URL 前加上相应前缀：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git -- &lt;code&gt;git+&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Mercurial -- &lt;code&gt;hg+&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Subversion -- &lt;code&gt;svn+&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Bazaar -- &lt;code&gt;bzr+&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;例如 Git 支持的格式为 git+file, git+https, git+ssh, git+http 等等。&lt;/p&gt;

&lt;p&gt;可以将需要安装的包写在一个依赖描述文件中，用 -r 参数指定该文件位置，pip 会解析该文件并安装合适的包，该文件通常被命名为 requirements.txt。依赖描述文件示例：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;# Requirement Specifiers:

pkg
pkg == 1.3
pkg &amp;gt;=1.2,&amp;lt;2.0
pkg == 1.*     # 模糊匹配，表示 1 版本均可，如 1.1, 1.2
okg!=1.3.5     # 除了 1.3.5 版本，其他版本均可
pkg~=1.4.2     # 兼容的版本，即大于 1.4.2 的 1.4 版本均可，类似 &amp;gt;= 1.4.2, == 1.4.*
pkg[foo, bar]  # 指定额外的依赖项

# 支持环境标志
pkg ==5.4 ; python_version &amp;lt; '3.8'
pkg; sys_platform == 'win32'

# 直接包含一个文件路径
./downloads/pkg-1.0.2-cp38-none-win32.whl
http://pkg.com/pkg-1.0.8-cp38-none-win_amd64.whl

# 从 git 仓库安装
git+https://github.com/hello/project.git
git+https://github.com/hello/project.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;一些安装示例：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 指定包和版本&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;pkg
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pkg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;1.0.4
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'pkg&amp;gt;=1.0.4'&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 指定依赖说明文件&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; requirements.txt

&lt;span class=&quot;c&quot;&gt;# 升级包&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--upgrade&lt;/span&gt; pkg
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-U&lt;/span&gt; pkg

&lt;span class=&quot;c&quot;&gt;# 以编辑模式安装本地项目&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--pre&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;   &lt;span class=&quot;c&quot;&gt;# 允许预发布版本&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; path/to/project

&lt;span class=&quot;c&quot;&gt;# 只安装指定包，不安装其依赖&lt;/span&gt;
pip instal &lt;span class=&quot;nt&quot;&gt;--no-deps&lt;/span&gt; pkg

&lt;span class=&quot;c&quot;&gt;# 安装到用户目录，而不是系统默认目录&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; pkg

&lt;span class=&quot;c&quot;&gt;# 指定安装目录前缀&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--install-option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;--prefix=/usr/local&quot;&lt;/span&gt; pkg

&lt;span class=&quot;c&quot;&gt;# 从 Git 仓库安装&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;git+ssh://git.example.com/project#egg&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;project
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;git+file:///home/user/projects/project#egg&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;project
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;git+https://git.example.com/project#egg&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;project

&lt;span class=&quot;c&quot;&gt;# 安装额外的依赖项&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;pkg[PDF]
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;pkg[PDF] @ git+https://git.repo/pkg@main#subdirectory=subdir_path&quot;&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; .[PDF]  &lt;span class=&quot;c&quot;&gt;# project in current directory&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;pkg[PDF]&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;3.0
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;pkg[PDF,EPUB]  &lt;span class=&quot;c&quot;&gt;# multiple extras&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 安装时不使用二进制包&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;pkg1 pkg2 &lt;span class=&quot;nt&quot;&gt;--no-binary&lt;/span&gt; :all:  &lt;span class=&quot;c&quot;&gt;# 所有包都不使用二进制&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;pkg1 pkg2 &lt;span class=&quot;nt&quot;&gt;--no-binary&lt;/span&gt; pkg1   &lt;span class=&quot;c&quot;&gt;# 仅 pkg1 不使用二进制&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 从指定的仓库源安装&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--index-url&lt;/span&gt; https://pypi.tuna.tsinghua.edu.cn/simple/ pkg

&lt;span class=&quot;c&quot;&gt;# 从指定路径安装：&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--no-index&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--find-links&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;file:///local/dir/ pkg
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--no-index&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--find-links&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/local/dir/ pkg
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--no-index&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--find-links&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;relative/dir/ pkg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;安装完成后，可以对包的依赖兼容性进行检查：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 检查单个包兼容性&lt;/span&gt;
pip check pkg

&lt;span class=&quot;c&quot;&gt;# 检查所有包兼容性&lt;/span&gt;
pip check
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;如果安装时指定了错误的版本，则会报错：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;lemon
Looking &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;indexes: https://mirrors.aliyun.com/pypi/simple/
ERROR: Could not find a version that satisfies the requirement &lt;span class=&quot;nv&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;lemon &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;from versions: 0.2.0, ... 2.26.0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
ERROR: No matching distribution found &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;lemon
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;所以，可以通过这种方式来查看可用的版本，直接运行 &lt;strong&gt;pip intall numpy==&lt;/strong&gt; （不指定任何版本号）也可以达到同样的效果。&lt;/p&gt;

&lt;p&gt;此外，还可以使用 &lt;code&gt;download&lt;/code&gt; 命令，只下载包到本地，而不安装，如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 下载包&lt;/span&gt;
pip download pkg

&lt;span class=&quot;c&quot;&gt;# 下载包到指定目录&lt;/span&gt;
pip download &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /tmp pkg

&lt;span class=&quot;c&quot;&gt;# 允许预发布版本，且不下载依赖&lt;/span&gt;
pip download &lt;span class=&quot;nt&quot;&gt;--no-deps&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--pre&lt;/span&gt; pkg

&lt;span class=&quot;c&quot;&gt;# 从指定源下载&lt;/span&gt;
pip download &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; https://pypi.tuna.tsinghua.edu.cn/simple/ pkg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;需要卸载已安装的包，则使用 &lt;code&gt;uninstall&lt;/code&gt; 命令：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 卸载包&lt;/span&gt;
pip uninstall pkg

&lt;span class=&quot;c&quot;&gt;# 不用手动确认，直接卸载&lt;/span&gt;
pip uninstall &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; pkg

&lt;span class=&quot;c&quot;&gt;# 卸载 requirements.txt 文件列出的包&lt;/span&gt;
pip uninstall &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;wheel&quot;&gt;Wheel&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://wheel.readthedocs.io/en/latest/&quot;&gt;Wheel&lt;/a&gt; 是 Python 的达标标准，这之前的主流打包格式是 &lt;strong&gt;egg&lt;/strong&gt; 文件。Wheel 遵循 &lt;a href=&quot;https://www.python.org/dev/peps/pep-0427/&quot;&gt;PEP-0427&lt;/a&gt; 标准，其本质是一个 zip 压缩文件，zip应用程序打开它。打包与安装 Wheel 文件都依赖 wheel 库，需要先安装它：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;pip install wheel
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;制作 wheel 文件可以使用 &lt;code&gt;pip wheel&lt;/code&gt; 命令，如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;pip wheel &lt;span class=&quot;nt&quot;&gt;--wheel-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/whl &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;--wheel-dir&lt;/code&gt; 指定生成 &lt;code&gt;.whl&lt;/code&gt; 文件的存储位置，最后指定包含 setup.py 文件的项目目录，示例中指定了当前目录。&lt;/p&gt;

&lt;p&gt;在项目目录中可以将安装依赖写入到 requirements.txt 文件中，然后用 &lt;code&gt;-r&lt;/code&gt; 参数指定，在制作 &lt;code&gt;.whl&lt;/code&gt; 安装包时会将 requirements.txt 里的安装依赖写入到 dist-info 里的 METADATA 文件中：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;pip wheel &lt;span class=&quot;nt&quot;&gt;--wheel-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/whl &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; requirements.txt &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;也可以直接在项目目录中使用 setup.py 的 &lt;code&gt;bdist_wheel&lt;/code&gt; 命令制作 wheel 文件：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;python setup.py bdist_wheel
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;安装 wheel 文件时直接指定 .whl 文件位置即可：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; ~/whl/pkg-1.0.0-py3-none-any.whl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;如果是在 windows 环境下，安装一些需要编译的包可能不是很容易，可以到 &lt;a href=&quot;https://www.lfd.uci.edu/%7Egohlke/pythonlibs/&quot;&gt;https://www.lfd.uci.edu/~gohlke/pythonlibs/&lt;/a&gt; 下载已经编译好的 whl 文件安装。&lt;/p&gt;

&lt;h2 id=&quot;list&quot;&gt;List&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;list&lt;/code&gt; 命令由于列出已安装的包，常用的参数有：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;-o, --outdated    列出可更新的包
-u, --uptodate    列出已经更新到最新版本的包
-e, --editable    列出所有可编辑的项目
-l, --local       只列出在虚拟环境中安装的包，也就是不列出全局安装的包
--user            只列出用户级别安装的包
--pre             包含预发布的版本和开发版本，默认情况下只包含稳定版本
--format          指定输出格式，包括 columns(默认), freeze, json 或 legacy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;使用示例：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pip list
Package                                           Version
&lt;span class=&quot;nt&quot;&gt;-------------------------------------------------&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-------------------&lt;/span&gt;
alabaster                                         0.7.12
altair                                            4.1.0
...

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pip list &lt;span class=&quot;nt&quot;&gt;--format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;json
&lt;span class=&quot;o&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;alabaster&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;version&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;0.7.12&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;, ...]

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pip list &lt;span class=&quot;nt&quot;&gt;--format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;freeze
&lt;span class=&quot;nv&quot;&gt;alabaster&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;0.7.12
&lt;span class=&quot;nv&quot;&gt;altair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;4.1.0
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;freeze&lt;/code&gt; 输出格式与使用 freeze 命令是同样的效果：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pip freeze
&lt;span class=&quot;nv&quot;&gt;alabaster&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;0.7.12
&lt;span class=&quot;nv&quot;&gt;altair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;4.1.0
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;freeze&lt;/code&gt; 命令通常用于将环境导出为 requirements.txt，以便用 &lt;code&gt;-r&lt;/code&gt; 安装指定安装：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 导出环境&lt;/span&gt;
pip freeze &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; requirements.txt

&lt;span class=&quot;c&quot;&gt;# 恢复环境&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;还可以使用 &lt;code&gt;show&lt;/code&gt; 命令查看已安装包的信息:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 查看包信息&lt;/span&gt;
pip show pkg

&lt;span class=&quot;c&quot;&gt;# 查看包信息，同时列出安装的文件&lt;/span&gt;
pip show &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; pkg
pip show &lt;span class=&quot;nt&quot;&gt;--files&lt;/span&gt; pkg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;config&quot;&gt;Config&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;config&lt;/code&gt; 命令可以用于管理配置，其基本用法为：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;pip config [&amp;lt;file-option&amp;gt;] list
pip config [&amp;lt;file-option&amp;gt;] [--editor &amp;lt;editor-path&amp;gt;] edit

pip config [&amp;lt;file-option&amp;gt;] get name
pip config [&amp;lt;file-option&amp;gt;] set name value
pip config [&amp;lt;file-option&amp;gt;] unset name
pip config [&amp;lt;file-option&amp;gt;] debug
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;选项参数包括：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;--global  使用系统全局配置
--user  使用用户配置
--site  使用当前虚拟环境配置
--editor &amp;lt;editor&amp;gt;  指定编辑器
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;示例（配置源）：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;pip config &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;global.index-url http://mirrors.aliyun.com/pypi/simple/
pip config &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;install.trusted-host mirrors.aliyun.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;设置的配置会写入相应的配置文件中，也可以手动修改配置文件来完成配置。各平台下的配置文件位置，Unix 环境：&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;th&gt;位置&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Global&lt;/td&gt;
&lt;td&gt;/etc/pip.conf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;$HOME/.config/pip/pip.conf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Site&lt;/td&gt;
&lt;td&gt;$VIRTUAL_ENV/pip.conf&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;MacOS 环境：&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;th&gt;位置&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Global&lt;/td&gt;
&lt;td&gt;/Library/Application Support/pip/pip.conf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;$HOME/.config/pip/pip.conf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Site&lt;/td&gt;
&lt;td&gt;$VIRTUAL_ENV/pip.conf&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Windows 环境：&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;th&gt;位置&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Global&lt;/td&gt;
&lt;td&gt;C:\ProgramData\pip\pip.ini&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;%APPDATA%\pip\pip.ini&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Site&lt;/td&gt;
&lt;td&gt;$VIRTUAL_ENV/pip.conf&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;此外，pip 在各平台上都会优先加载 PIP_CONFIG_FILE 环境变量指定的配置，pip 加载配置文件的&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PIP_CONFIG_FILE&lt;/li&gt;
&lt;li&gt;Global&lt;/li&gt;
&lt;li&gt;User&lt;/li&gt;
&lt;li&gt;Site&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;配置文件示例：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;[global]
quiet = 0
verbose = 2
timeout = 60
no-cache-dir = false
index-url = https://pypi.tuna.tsinghua.edu.cn/simple/

[install]
ignore-installed = true
no-dependencies = yes

[freeze]
timeout = 10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;mirror&quot;&gt;Mirror&lt;/h2&gt;

&lt;p&gt;常用镜像地址：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;官方： https://pypi.org/&lt;/li&gt;
&lt;li&gt;豆瓣： https://pypi.doubanio.com/simple/&lt;/li&gt;
&lt;li&gt;阿里云： https://mirrors.aliyun.com/pypi/simple/&lt;/li&gt;
&lt;li&gt;腾讯云： https://mirrors.cloud.tencent.com/pypi/simple/&lt;/li&gt;
&lt;li&gt;华为云： https://mirrors.huaweicloud.com/repository/pypi/simple/&lt;/li&gt;
&lt;li&gt;清华大学： https://pypi.tuna.tsinghua.edu.cn/simple/&lt;/li&gt;
&lt;li&gt;中国科学技术大学： https://pypi.mirrors.ustc.edu.cn/simple/&lt;/li&gt;
&lt;li&gt;华中理工大学： https://pypi.hustunique.com/&lt;/li&gt;
&lt;li&gt;山东理工大学： https://pypi.sdutlinux.org/&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;更多使用方式可查阅 pip 官网文档：&lt;a href=&quot;https://pip.pypa.io/en/stable/&quot;&gt;https://pip.pypa.io/en/stable/&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 28 Nov 2021 00:00:00 +0800</pubDate>
        <link>https://donothing.site/2021/11/28/pip/</link>
        <guid isPermaLink="true">https://donothing.site/2021/11/28/pip/</guid>
        
        <category>python</category>
        
        
        <category>Python</category>
        
      </item>
    
      <item>
        <title>旅途</title>
        <description>&lt;h3 id=&quot;part-7285f63a6c5fdf41&quot;&gt;一 序章&lt;/h3&gt;

&lt;p&gt;中秋假期第一天，我的一位朋友邀请我去他家一起吃个中秋饭。饭后，他给我展示了他最近在玩的一款游戏，也让我尝试玩了下。我几乎不怎么玩游戏，所以玩了一会觉得无趣，就说让他玩，我看着。他应该觉察到了我对这游戏的无感，于是打开了一款新的游戏。&lt;/p&gt;

&lt;p&gt;此时，母亲来了电话，我本来准备中秋节那天才给她去电话的，结果才刚放假她就先打来了。一个人孤生在外多年，母亲总是担心我过得不好。一如往常，我跟她聊了些家常，问了些家里天气怎么样，有没有买月饼，最近家里吃的什么菜，父亲最近在干嘛之类的问题。最后，也是一如往常的，她说，“要照顾好自己啊！”&lt;/p&gt;

&lt;p&gt;在我打电话的间隙，朋友先玩起了打开的新游戏，待我挂了电话，他说：“来试试这个游戏，你应该喜欢。”&lt;/p&gt;

&lt;p&gt;确实，这款休闲类游戏我还挺喜欢的。游戏美术做得非常好，画面精美，赏心悦目。音乐也别具一格，极为动听。风格恬静舒适，操作也简单。&lt;/p&gt;

&lt;p&gt;我问他，这游戏叫什么，他说叫《旅途》（又名《风之旅人》）。&lt;/p&gt;

&lt;h3 id=&quot;part-7285f9406605d4f1&quot;&gt;二 中秋&lt;/h3&gt;

&lt;p&gt;中秋那天，我又去了一同学家那儿蹭饭。是的，这个中秋节我都在外面蹭饭。前些年，每逢过节，在北京的几个同学常常会聚一聚。远在他乡，那些同学、朋友就算是亲人了。不过，岁月流逝，各自都渐渐有了自己行进的方向，要再聚在一起，不是一件容易的事。&lt;/p&gt;

&lt;p&gt;吃过饭，又跟同学聊了聊工作、生活上的事。不知不觉就快下午六点了，同学还想留我一会，说等晚上一起吃个月饼赏个月。我笑道：“有谁真正的赏过月？月饼我早就吃过了！”&lt;/p&gt;

&lt;p&gt;我是有点觉得如今的吃月饼有点形式主义，也可能是我觉得自己不需要那么多的仪式感。但月应该是有人认真赏过的，“胜花影、春灯相乱”，“孤兔凄凉照水，晓风起、银河西转”。我不知道自己是否真正的赏过月。&lt;/p&gt;

&lt;p&gt;在我看来，所谓的中秋团圆，只不过是古人的期望罢了，因为古人的诗篇中，大多都是借月怀思。“举头望明月，低头思故乡”，这又是哪里来的团聚呢？只是，羁旅漂泊，总得有些寄托罢了。&lt;/p&gt;

&lt;p&gt;十一年前，去家八千里求学，一趟一趟的路途，越过山河，掠过大海，横穿沼泽，出关入城，此后故乡便常常只在记忆里了。&lt;/p&gt;

&lt;p&gt;“今夜月明人尽望”，不管我们身处何处，头顶都是同一轮明月。秦镜满时，立于其下，我也愿意相信，远方的亲人若是抬头，也可以看到我在圆月里小小的影子。在这个世界上，我们都应该庆幸有日月同天。&lt;/p&gt;

&lt;h3 id=&quot;part-7285f693b7c9e1a8&quot;&gt;三 启程&lt;/h3&gt;

&lt;p&gt;我回家刚进门，本来想歇一会，再往家里去个电话。还没等坐下，母亲就打来了电话。&lt;/p&gt;

&lt;p&gt;“嗯，妈。”&lt;/p&gt;

&lt;p&gt;“你奶奶病重，你看看能不能赶紧回来一趟。”&lt;/p&gt;

&lt;p&gt;我坐下，喝了口水。我感觉自己很平静，心里没有什么波澜。世事有常，或许潜意识里早就觉得，有些事终究会发生。可是，我真的已经准备好面对某些事吗？&lt;/p&gt;

&lt;p&gt;愣坐了一会儿，我才意识到该收拾下行李了。行动起来后，发现自己有些莫名的恍惚。每做完一个动作之后，总不知道接下来要做什么。关于奶奶的一切开始不停地涌上心头。&lt;/p&gt;

&lt;p&gt;父亲又来了电话。&lt;/p&gt;

&lt;p&gt;“爸！”&lt;/p&gt;

&lt;p&gt;“你奶奶已经走了！”&lt;/p&gt;

&lt;p&gt;“人生七十古来稀”，在我们家族中，奶奶这一辈人中现在仅三爷爷还在世了。三爷爷已经接近九十高寿。奶奶享年七十八岁。&lt;/p&gt;

&lt;p&gt;我的行李就一些简单的衣物和日常用品，可是却足足收拾了三个多小时。&lt;/p&gt;

&lt;p&gt;凌晨的北京城很空。像是这初秋的轻风，将昨日白昼的嘈杂慢慢拂去，得此深夜片刻宁静。其实，天地之间自有其规则，繁华、喧闹之后总有萧寂，亦如昼夜交替，阴阳更迭，不断轮回。这么空阔的道路，师傅开车仍然很稳，行进有度。&lt;/p&gt;

&lt;p&gt;我站在登机口旁边的玻璃窗前，看着地平线一点一点的呈现，然后泛红，直到旭日升起。这座城市的喧闹又要开始了。&lt;/p&gt;

&lt;p&gt;每次乘坐交通工具时，总会有广播提示你说，“祝您旅途愉快”。&lt;/p&gt;

&lt;p&gt;我的短暂的旅途又开始了。&lt;/p&gt;

&lt;h3 id=&quot;part-7285fc642983346c&quot;&gt;四 往事&lt;/h3&gt;

&lt;p&gt;我想起了外婆。她最后一次去我们家，给我们带了一副新碗，还有她自己种的一些菜。那年是一个特殊的年份，具体叫什么年份我已经记不清了，家里边的一种风俗，说是妈妈要给女儿家置办新碗，以图吉利。当时就我在家，外婆还没吃饭，我就给她做饭。饭做好端上桌时，她看了看说：“我忘了告诉你，我不能吃辣的了”。她说她也不咋饿，就简单用茶水泡了一碗饭吃。&lt;/p&gt;

&lt;p&gt;彼时，我已常在县城里上高中，已经很少去外婆家了。我没有意识到，外婆已经生病了。此后，我便再也没有见过外婆。外婆不在后，有一段时间里，恍恍一个老人身影走过，我总会以为是外婆。嘈杂的人声里，如果有老人的声音，总感觉是外婆在说话。好像在潜意识里，外婆仍然还在。可是，猛一回头，才意识到……&lt;/p&gt;

&lt;p&gt;我也想起了外公。外公腿有风湿病，时常会有剧痛。母亲说应该是以前种稻谷守田时，常在田埂旁过夜，以致患上了风湿。后来外公生了一场大病，之后就是话说得不大明白了，其他都还算正常。&lt;/p&gt;

&lt;p&gt;外婆走后，次年，一天清晨，小姨说当时外公还坐在屋檐坎上择菜，突然就倒地了，然后就失去了意识。舅舅打电话告诉母亲时，我看见母亲哭了。&lt;/p&gt;

&lt;p&gt;我们赶去外公家时，屋里坐满了人，外公躺在椅子上，闭着眼睛，张着嘴一直在喘气，但是已经怎么也叫不醒了。舅舅说救护车已经来过了，大夫说这个情况带去医院结果恐怕也不理想。我不知道外公还能不能感觉到难受，如果能，一定很痛苦。大抵过了十多个小时后，外公也走了。&lt;/p&gt;

&lt;p&gt;至今，我对医学依然一无所知。我以为人只要还有一口气在，就能救回来。至少那个时候，我真希望自己有能力能把外公救回来。那个时候我特别希望自己以后能够成为一名医生。&lt;/p&gt;

&lt;p&gt;外婆家的灶头上总是常年挂着腊肉舍不得吃，每次去外婆家时她都会切一块下来。干辣椒炒腊肉特别的香，我以前特别喜欢吃，就是外婆家的腊肉有点咸。&lt;/p&gt;

&lt;p&gt;我没见过我的亲爷爷。以前似乎听奶奶讲过，大概在父亲七岁那年，爷爷喝醉了酒，跌倒进了水库里。后来我也没有仔细问过，我觉得这个事可能有些忌讳。在很长一段时间里，我以为继爷爷就是爷爷。&lt;/p&gt;

&lt;p&gt;继爷爷在我生命里存在的时间也只短短几年，我对他的记忆也已经很模糊了。我现在隐隐约约还记得是，在冬天的时候，爷爷总是会在灶头前的煤坑里生一堆火，然后大家一起围着火堆吃饭，还有就是，有一次我跟堂哥好奇，趁着爷爷不在，偷了爷爷的草烟卷来尝着抽，至于有没有被呛着，或者有没有挨爷爷骂，也都已经记不清了。&lt;/p&gt;

&lt;h3 id=&quot;part-7285f98fc916b9d7&quot;&gt;五 奶奶&lt;/h3&gt;

&lt;p&gt;我能回想起的关于奶奶的最早的记忆，是我很小的时候，我拿着奶奶给的米花饼在粪桶上边吃边拉屎。奶奶发现了，赶紧走了过来，“哎呀，孙儿呀，你怎么又在吃，又在拉呀！”那个时候，我应该也就两三岁的样子，这件事已经很久远了，有些模糊，但也很深刻。实际上，我都分不清这是一场梦，还是真真切切的与奶奶的过往。反正自那以后，我记住了，边吃东西便拉屎是不好的。我们刚出生时，对世界一无所知。而后慢慢成长，受亲人教化，学会做人。这便是养育之恩。&lt;/p&gt;

&lt;p&gt;小时候，奶奶家养了很多鸭子，傍晚鸭子回巢，会在院坝里站成一片一片的。我总是要去撵它们玩，然后奶奶就喊，“孙儿啊，快回来，让小鸭鸭们回家！”&lt;/p&gt;

&lt;p&gt;奶奶会做很多很多好吃的，有好多我已经叫不出名了。我记得快过年时，奶奶都会做苕粉、绿豆粉、汤包，米酒、甜粑、酥肉等等。小时候我最喜欢吃的应该是绞绞（方言叫法，与麻花差不多，形状似蝴蝶结，面团拉成线状，缠绕绞起来再经油炸而成），最不想吃的是玉米饼，因为觉得吃起来很糙。&lt;/p&gt;

&lt;p&gt;奶奶特别喜欢做豆腐，就是现在每年过年，她都还会做豆腐，然后送到我们家一些。以前奶奶生日的时候，会有很多人来看望她，她总会在生日前一天推磨磨豆，把豆腐先做好。豆腐制作的最后一道工序是，在点卤后，盛入模具挤水压实，通常需要一夜。做豆腐的过程中，除了最终成型的豆腐外，还能产生其他几道菜：滤过的豆渣，再切点碎菜叶进去炒一炒，这道菜我们成为豆腐渣；喜欢吃豆花的话，可以直接在点卤后先直接盛一些出来；点卤之后滤出的水，我们称为告水（方言叫法），略带酸味，带着煮熟的豆香，可助消化（很早以前，外婆家的邻居也是做豆腐的，所以小时候在外婆家时总喝）。&lt;/p&gt;

&lt;p&gt;过端午节的时候，奶奶也经常会去割芭蕉叶来做麦粑（与馒头差不多的做法，只不过会残留芭蕉叶的香气，如果有红糖兑入会更好吃）。菜园子边上的那几棵芭蕉树仍然还在，硕大的叶片迎风而展。几十年了，不知道奶奶去割了多少次芭蕉叶，做了多少次麦粑。&lt;/p&gt;

&lt;p&gt;渐渐地，奶奶腿脚也不太利索了，但她仍然种了很多菜，又养了好多鸡。每次回家去看望奶奶，奶奶都要单给我做一碗鸡蛋吃。她的做法是，鸡蛋整个用油煎完，然后热锅加水煮。这样做汤特别鲜，还可以加点挂面一起煮。父亲也喜欢这样的做法，每次母亲过生日，他都会这样做给我们吃。&lt;/p&gt;

&lt;h3 id=&quot;part-7285e0f2c10992c3&quot;&gt;六 回家&lt;/h3&gt;

&lt;p&gt;我从父亲的摩托车上下来，看见母亲和几位伯妈坐在山廊头（方言，指房屋两侧的空地）聊天。看见我回来，她们也都看向我，我跟她们一一打了招呼。在场的人还不多，很多亲戚都在外地，他们应该大多都还在途中，像我一样匆匆赶来。&lt;/p&gt;

&lt;p&gt;母亲对我说：“去看看你奶奶吧！”&lt;/p&gt;

&lt;p&gt;我回头，看见半轮夕阳挂在树梢，将落未落。橘红色的晚霞浮在山棱，映得西边很是绚烂，屋顶黑灰的瓦片上也泛着金黄。余辉打在脸上，很柔和，舒服。天空开始慢慢暗下来，也起了风。我远远看见长长的芭蕉树叶轻轻地摆动着，像无声的海浪。&lt;/p&gt;

&lt;p&gt;奶奶走的很安详，只像是睡着了，但怎么也叫不醒了。&lt;/p&gt;

&lt;p&gt;我觉察不出大家的心情。几位伯伯、叔叔在院坝里打牌、搓麻将。或许，像爸妈他们那样年纪的人，生死都已经见惯了。屋里兰兰（二叔家大女儿）和小丽（二叔家小女儿）静坐着，我进屋时她们没有跟我打招呼。我轻轻坐下来，很是无措，不知道该说点什么。慢慢地，我感觉这气氛开始压得我有些喘不过气。于是，我决定打破这“僵局”。&lt;/p&gt;

&lt;p&gt;“兰兰，有闲着的充电器吗，我手机快没电了。”&lt;/p&gt;

&lt;p&gt;“你是什么手机，苹果？”&lt;/p&gt;

&lt;p&gt;“就那种安卓圆口的就行！”&lt;/p&gt;

&lt;p&gt;“什么牌子的？”&lt;/p&gt;

&lt;p&gt;“哈哈，你可能没听过。”&lt;/p&gt;

&lt;p&gt;兰兰满脸疑惑，我揭开手机壳给她看。她噘了噘嘴，“哈哈哈，确实没听过。有俩充电器他们都刚充上了，你得等会儿了。”&lt;/p&gt;

&lt;p&gt;小丽性格内向，鲜少说话，我跟她见得少，也不熟络。兰兰从小便是奶奶带大的，二叔和二婶常年在外打工。如今，最伤心的人，应该就是兰兰了。以前，每逢赶集，兰兰都会站在屋檐坎边上等奶奶赶集回来。奶奶每次回来都会买很多好吃的，像油糍粑、麻饼、糖麻圆、米豆腐等等。赶集的人们从早到晚络绎不绝，大都结伴而行，有说有笑。其实，小时候最开心的一件事，就是有机会能去赶集。奶奶赶集有时候会回来得很晚，但兰兰总是一直等着，有时候会等到黄昏日落，有时候也会等到月出惊鸟。奶奶也不会总是很晚回来，因为她知道兰兰在家等着她，或许有时候只是让什么事给耽搁了。&lt;/p&gt;

&lt;p&gt;父亲和二叔忙着张罗各种各样的事，母亲仍然在跟几位伯妈聊着天，也有其他亲戚陆陆续续的赶来。大家看着都很平静，我只来回踱步，我应该也是平静的。但我清楚着一件事：爸爸妈妈都永远的没有爸爸妈妈了。&lt;/p&gt;

&lt;h3 id=&quot;part-7285f6583112b2ba&quot;&gt;七 明月&lt;/h3&gt;

&lt;p&gt;奶奶家靠着山腰，朝着东方，也在南面一座山的山脚下，不远处还有一座山横在前面，像是一道屏风。这里的日出、日落、月出、星空都美极了，也是我出生、长大的地方。&lt;/p&gt;

&lt;p&gt;这几日，我站在兰兰曾经等奶奶赶集回来的地方，迎着皎月升起，又送她落下。“月是故乡明”，杜子美没有骗我，这些年在外，我从未见过哪里的月亮，能比这里的更明亮、澄澈，美得不可方物。偶尔会有浮云掠过，为碧空添了些点缀，也是别有一番风致。&lt;/p&gt;

&lt;p&gt;只是，每过一日，明月都会缺一部分，再往后的话就该渐渐如钩了。月圆月缺，周而复始，好像这个世界的运转，都是一个一个的轮回。看着月亮悠悠地走到西头，我想我也送了一回月。幼安曾说，前人诗篇只有待月，于是他用《天问》体写了一首送月词：&lt;/p&gt;

&lt;p&gt;“可怜今夕月，向何处，去悠悠？是别有人间，那边才见，光影东头？是天外空汗漫，但长风浩浩送中秋？”&lt;/p&gt;

&lt;p&gt;月亮也自有她的旅途，我们看见她落下，但有人正看着她升起。是别有人间，那边才见，光影东头！我们看着她升起时，也正有人看着她落下。&lt;/p&gt;

&lt;p&gt;这轮明月，在这个时空中，已经照过了无数的人。“今人不见古时月，今月曾经照古人”，也曾照着奶奶晚归，照着奶奶在旁边的地里种下种子，照着奶奶从地里挖回菜做夜饭，甚至可能还照着奶奶割回芭蕉叶。奶奶将这一生都献给了这片土地，披星戴月，养育了我们。&lt;/p&gt;

&lt;p&gt;如今已是秋之中了，再过些时日，清晨路边的小草上会渐现白色的露珠。&lt;/p&gt;

&lt;p&gt;我极力地想要去记住我所看到的美，因为我不清楚，有时我们看着的景，见着的人，是不是就是最后一次了。&lt;/p&gt;

&lt;h3 id=&quot;part-7285e0def1f5678b&quot;&gt;八 轮回&lt;/h3&gt;

&lt;p&gt;那天，我在朋友家玩游戏玩到了很晚，直到通关才回。朋友说，这款游戏的主题主要是讲“轮回”。&lt;/p&gt;

&lt;p&gt;游戏的开场是一片无垠的沙漠，主角以一束光的形式，从天而降，来到沙漠里，她是一名无名的旅者。旅者需要穿越沙漠开始冒险，在翻越无数山脉，走过无数桥梁后，会看到远处有一座发着光的高山，那是旅途的终点。&lt;/p&gt;

&lt;p&gt;在冒险的旅途中也会遇到一些简单的怪兽，会攻击你。也可能会遇到同伴（其他玩家），与你并肩行走，共历风雨。旅途的最后需要爬上一座很高的雪上，山上风雪很大，这里稍微有些困难。但仍然需要无所畏惧地往前走，直到精疲力尽，倒在一片白茫茫的雪域之中。接着，你又醒来了，全身泛着金光，被卷入一个漩涡之中，来到了一个明亮、鲜艳的世界，像是“天堂”。此时，你可以无限的飞翔，你涅槃重生了。&lt;/p&gt;

&lt;p&gt;继续往前走，在山的最顶端有一道耀眼的白光直通天际，走向其中，你化成了一道光，像流星一样划过天空，又回到了你出发的地方。&lt;/p&gt;

&lt;p&gt;那些故去的人，是否也会越过重生之门，轮回，回到新的起点呢？&lt;/p&gt;

&lt;p&gt;我们看着生，看着死，又看透了生死吗？有死亡，有新生，那么，我该相信有轮回吗？&lt;/p&gt;

&lt;h3 id=&quot;part-7285f8a1ab0c5715&quot;&gt;九 起点&lt;/h3&gt;

&lt;p&gt;走出机舱门，我感觉到北京的天气凉了一些。人们背着行囊，拖着行李，奔波在各自的旅途中。活着的人还有很多路要走！&lt;/p&gt;

&lt;p&gt;其实，我们这一生整体也就像是一趟旅途。有些人的旅途已经结束了，有些人的旅途才刚刚开始，而大部分人都正在路上。&lt;/p&gt;

&lt;p&gt;我的这趟旅途算是结束了。但是，也回到了起点，新的旅途又开始了。无论现在你是何种状态，你都在路上！&lt;/p&gt;

&lt;p&gt;&lt;em&gt;公元二零二一年农历八月十六至二十于旅途中&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 26 Sep 2021 00:00:00 +0800</pubDate>
        <link>https://donothing.site/2021/09/26/trip/</link>
        <guid isPermaLink="true">https://donothing.site/2021/09/26/trip/</guid>
        
        <category>西窗梦集</category>
        
        
        <category>西窗梦集</category>
        
      </item>
    
      <item>
        <title>我如何每日从北京酒仙桥到加州硅谷上班</title>
        <description>&lt;p&gt;&lt;strong&gt;文/赵亮  摘自《科幻世界》2014 年 3 月刊&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/kuanghy/pichub/master/2020/05/f76f4ca1a3e7ec819720561c7e60ce2c.jpg&quot; alt=&quot;图/蔡定一&quot;&gt;&lt;/p&gt;

&lt;p&gt;我不知道该如何向你们说这件事儿——轻描淡写地说吧，估计你们所有人都会扑哧一笑，觉得我一定是嗑药嗑太多脑子坏掉了，多半还患上了轻度妄想症；但要说得言之凿凿，又怕你们执意要我证明给你们看，那我可是一点辙儿都没有，别到时再好死不死落个妖言惑众的名声，自讨没趣。&lt;/p&gt;

&lt;p&gt;于是前思后想之后，我决定用这个既带有地摊玄幻小说风格，又秉承长微博技术贴标准的模棱两可的标题缓冲一下，总之进可攻退可守。你若相信，我便晴天，你若不信，那我也好顺水推舟地承认这是篇不成功的科幻小说习作，至少我的结局不至于像凯文·斯帕西在《K星异客》中饰演的那个从距地球一千光年以外的天琴座K-PAX星球以超光速来地球游览的普洛特那样，被你们不分青红皂白地当做精神病人扭送到曼哈顿或回龙观精神病院吧。&lt;/p&gt;

&lt;p&gt;因此，你们大可以把前面这两段话当做我从法律上推卸自我责任的声明。是的，我不想多惹事，不过，请允许我在认真给你们讲述这件听起来离奇透顶的事情之前再最后多唠叨一句——不管你相信也好，怀疑也罢，请记住那个五百年前生活在雅芳河畔斯特拉特福叫做威廉·莎士比亚的英国人说的一句话——“凡是过去，皆为序曲”。&lt;/p&gt;

&lt;p&gt;好了，开始讲我的故事。&lt;/p&gt;

&lt;p&gt;这事儿说起来也挺简单：我住的地儿在北京东北边儿，你若走四环路的话，从东风北桥下来之后拐到酒仙桥路，看到一个和新修的颐堤港遥相对望的叫做晶都国际的小区，那就是了。我每天工作八小时，准时上下班，基本风雨无阻，经常会和老婆去三元桥边儿上的“鹿港小镇”吃晚餐，没什么特殊的。当然，唯一可能和诸位有点儿不同的就是，我上班的地点在硅谷一个叫做红杉海岸的小城，对，就是甲骨文公司总部的所在地，而且，那个，我，每天，都回家。&lt;/p&gt;

&lt;p&gt;对，你没看错，我每天要从酒仙桥去硅谷上班。我知道这听起来太狗血，说实话，直到今天，我都有一种不真实的感觉，生怕这是我臆想出来的一个梦境。为此我做了许多实验，结论就是，如果不是整个世界都在陪我演一出疯狂闹剧的话，那么按照夏洛克·福尔摩斯先生那个著名的“当你把一切不可能的结论都排除之后，那剩下的，不管多么离奇，也必然是事实”的假设推导下，唯一的可能性就是，这一切都是真的！&lt;/p&gt;

&lt;p&gt;Ok，我明白我说得有一点语无伦次，好吧，请让我深呼吸一下，从头慢慢道来0&lt;/p&gt;

&lt;p&gt;2009年，我从北京来到加州求学，和所有漂泊在异乡的学子一样，交替体验着新鲜感与思乡病。&lt;/p&gt;

&lt;p&gt;2010年春天，我搬到了离斯坦福不远的一个叫做贝蒙特的小镇，因为我在这附近找到了一份工作，而所有的一切，都是从那时开始的。&lt;/p&gt;

&lt;p&gt;在公司里，我认识了一位很厉害很厉害的前辈，（什么，我只说了两个“很厉害”？那一定要再补一个才对，是很厉害很厉害很厉害的前辈！）这位前辈十六岁从哥伦比亚大学毕业，二十岁时拿到了斯坦福大学电子电气和生物技术的双料博士，是卡内基梅隆的客座教授，还是美国海军现役军官，曾经是英特尔年轻的副总裁级，现在则是一个几百亿美元对冲基金的合伙人（同时也是我们公司的董事会成员之一），他还是一个智商在170以上的意大利裔天才，最不可思议的是，在拥有了上述这一切的同时，他才三十四岁。&lt;/p&gt;

&lt;p&gt;请别怪我啰唆，因为长这么大能让我有这种高山仰止感觉的人毕竟不多，更何况，倘若不是因为这位前辈，我永远也不可能窥到这个号称21世纪被发达国家隐藏得最好的科学机密。&lt;/p&gt;

&lt;p&gt;虽然早就知道以美国为首的西方国家对我们进行技术封锁，但我始终以为，这些封锁造成的结果顶多让我们的技术落后西方国家一两代罢了，就像我们有歼-10、人家有F-22一样，我根本没有想到原来这种差距居然是……怎么说呢，用那位前辈的原话就是“蒸汽时代和电气时代的类比已经不足以说明问题了，应该是，麻瓜世界和魔法世界的差别吧”。&lt;/p&gt;

&lt;p&gt;我想读到这里的诸位一定会龇龇牙，从牙缝中发出一声不屑的冷笑。没关系，请尽管笑，我特理解，因为当那位前辈第一次向我如此描述他所认为的发展中国家和发达国家之间的科技差距时，我也从牙缝中发出了同样的冷笑啊。但不幸的是，在听完他的阐述，并且亲自经历过那一切后，我的牙缝中就只剩下冷了，笑容则全都凝固了。&lt;/p&gt;

&lt;p&gt;这件离奇的事情发生在一个平常的午后，我在公司的咖啡厅里偶遇了这位前辈，他大概是恰好来公司开股东会议，而最近公司的绩效不错，所以他看起来心情颇佳。闲聊之际，话题自然而然就被硅谷特有的万有引力所吸引，滑向了高科技。&lt;/p&gt;

&lt;p&gt;“我上周去上海开会，见了你们中国的几个科学家，说实话，中国的科技水平明显还停留在上个世纪。”这位前辈咂了一口咖啡。&lt;/p&gt;

&lt;p&gt;“开什么玩笑，我们的载人飞船和空间站可是刚刚完成对接啊。”我情不自禁地反驳道。&lt;/p&gt;

&lt;p&gt;“载人飞船？你还不如说你们还发现了盘尼西林呢！”那位前辈听完我愤愤不平的言语后揶揄地说，“仅在休斯敦，在太空工作站工作过六个月以上的人数就超过了得州所有的牛仔，你以为《太空牛仔》这部电影的剧本是克林特·伊斯特伍德凭空想出来的吗？说实话，1969年之后，航空航天就彻底沦为一门应用学科了，真正的科学家早就把目光投向了别处。这么说吧，发展中国家和发达国家之间的差距，用蒸汽时代和电气时代的类比已经不足以说明问题了，应该是……”他慢条斯理地吹了吹摩卡上漂着的那层奶泡，那170+的智商无疑在高速运转，试图找出一个邪恶的词汇来描述这种差距。&lt;/p&gt;

&lt;p&gt;最终，他眨了眨眼，说出了那句我甚至以为自己听错了的话：“麻瓜世界和魔法世界的差别吧。”&lt;/p&gt;

&lt;p&gt;我有点儿不可思议地瞅着这位前辈，试图在他的眼中找到那个“哈哈，我在开玩笑啦”的神色，但是他的眼神狡黠归狡黠，却没有一丝开玩笑的意思。不过我也不甘示弱，马上反唇相讥：“我承认中国和美国在不少科学领域的确存在着巨大的鸿沟，但麻瓜世界和魔法世界的差别……拜托，你这也有点儿太言过其实了吧……”&lt;/p&gt;

&lt;p&gt;“言过其实？或许吧。”这位前辈笑了笑，“在我的定义里，蒸汽时代和电气时代的差距，是当一个蒸汽机师第一次看到电动机的时候，他一定会十分惊讶地发现这个机器和他所了解的热力学机器十分不同，但是他不会诧异到认为是幽灵驱动了这一切，而是会合理地假定这个机器是按照某种他所不了解的原理所运行的。”他在此处停顿了一下，用眼神询问我是否认同，我缓缓地点了点头，于是他接着说，“而麻瓜世界和魔法世界的差别是当一个麻瓜第一次看到一个魔法师把飞路粉（floo powder）洒在身上然后钻进壁炉里消失得无影无踪的时候。你看过《哈利·波特》吧？嗯，你明白就好，他的唯一反应一定是holy shit！黑魔法！”说到此处，他夸张地做了一个受到惊吓的表情，然后把自己也逗乐了。&lt;/p&gt;

&lt;p&gt;我听罢反而长舒了一口气，唇角挂上了一丝冷笑，原来前辈只是追求语不惊人死不休的效果罢了，所以我有点儿挑衅地说：“既然这样，那么，魔法师，请向我这个麻瓜展示一下你们的魔法世界吧，让我也有机会holy shit一下，多好啊。”&lt;/p&gt;

&lt;p&gt;想不到他马上站起来说：“好啊，那我们就干脆从飞路粉开始吧。”我有点儿不知所措地瞪着他，怀疑他最近是不是报名参加了什么即兴表演班——最近硅谷流行这个——然后拿我当观众做练习了。不过他没有给我多少迷茫的时间，掏出车钥匙冲我挥了挥手，“走啊，坐着干吗，想见识飞路粉的话，我们得找一个最近的宜家才行！”&lt;/p&gt;

&lt;p&gt;飞路粉？宜家？他不是疯了吧？但是看他气定神闲信心笃定的样子，又一点不像是恶作剧。不管怎样，我还是跟着他上了车，直奔加州101高速，往圣何塞方向驶去——难道真的要去宜家？我知道在帕罗奥图边上的确有一家宜家家居。&lt;/p&gt;

&lt;p&gt;“嗯，那个，我知道听起来很傻，不过我们到底要去哪里？真的是宜家？”坐在车上我还是忍不住发问了。&lt;/p&gt;

&lt;p&gt;“你不是要见识一下我们的黑魔法吗？宜家的飞路粉电梯应该算是黑魔法101课程吧。”他兴致盎然地说。&lt;/p&gt;

&lt;p&gt;“……”我彻底无语了，如果这是个玩笑的话，我真的已经找不到笑点在什么地方了。&lt;/p&gt;

&lt;p&gt;“Okay，不开玩笑了，我真的带你去看一下现实存在的飞路粉。别笑，我知道这个词听起来太孩子气。”他耸了耸肩，“不过你也不能怪我，因为J·K·罗琳的小说太流行了，所以当这个产品2004年刚研发出来的时候，所有的人都立刻把它叫做飞路粉了。”&lt;/p&gt;

&lt;p&gt;“噢，一个叫做飞路粉的产品？我怎么从来没有听说过？”我有点儿好奇了。&lt;/p&gt;

&lt;p&gt;“你没听说过太正常了，就连美国人也不是每个人都知道它的存在——哈，幸好你认识我，今天你要大开眼界了。”他扭头冲我笑了笑，“当然，这种信息封锁也是无奈之举，你知道我们在二战后对科技领域进行了巨大的投资，初期当然是为了和苏联搞军备竞赛，但后来则意外地在基础物理学领域取得了巨大突破。你知道科学发展是有加速度的，想象一下从罗盘六分仪发展到全球定位系统用了多长时间，再想象一下从阿波罗11号4KB内存的导航控制计算机发展到尧字节用了多长时间你就明白了。井喷式的科技发展最初给美国带来的是惊喜，我们也曾兴致勃勃地试图将这些新的学术成果和技术推广给西方盟友之外的发展中国家，但是，‘9·11事件’的发生让美国政府开始重新审视国家安全问题，他们开始担忧，倘若这些比核能强大几万倍的新技术落到一些道德准则和制度规范都不健全的国家政权手里的话，后果不堪设想。在意识到这一点之后，以美国为首的西方国家开始有计划地封锁一些高端的科学研究成果和技术，别说对中国，有些新的研究成果即便是对美国最亲密的盟友，倘若该国没有一定级别，都绝对接触不到。当然，我今天带你看的这个东西离最先进的研究成果还差很远很远，但相信我，这已经足以颠覆你的大脑了。”他一边开车，一边做出一个大脑爆炸的手势。&lt;/p&gt;

&lt;p&gt;说实话，听他说上述这段话的时候，我还是觉得他在开一个有关历史阴谋论的玩笑，毕竟，倘若基础物理学真有像他所说的如此巨大的突破，没有理由其他国家的科学家连一点蛛丝马迹都没听到，难道那些国际学术杂志和诺贝尔奖都是演戏吗？&lt;/p&gt;

&lt;p&gt;“演戏？哈哈，你说得太对了！”他哈哈大笑，“杰克，和你说一件我不该说的事情——记住，下面这句话我从来没有说过，你倘若无端地知道了，那也绝对不是从我这里听到的，明白？”他看了看了我，我忙不迭地点头，听八卦的心态我还是很足的。&lt;/p&gt;

&lt;p&gt;“为了封锁最新的研究成果，整个西方世界就是在给发展中国家演戏。你知道，就像当年斯大林的《真理报》一样，至于瑞典皇家科学院都根本就是在作秀，诺贝尔奖就是一个prop。prop你懂吗？就是演戏的道具，骗你们的玩意儿而已！别说诺贝尔奖了，你以为宜家真的是卖家具的商场吗？别天真了，瑞典可不是出木匠的国家！”&lt;/p&gt;

&lt;p&gt;我彻底晕了，如果这一切只是为了一个恶作剧的话，那我只能说它太无厘头了，不过看着他信誓旦旦的样子，我还是决定冒险问出这个可能会被他嘲笑一辈子的问题：“那么……你刚才说的飞路粉到底是什么东西？如果说这背后的技术涉及你们美国的国家安全的话，那你让我见识这种‘黑魔法’，不会把我‘阅后即焚’吧？”&lt;/p&gt;

&lt;p&gt;“‘阅后即焚’？哈哈，杰克，你太逗了，你的英语造诣很高啊！放心，既然我敢让你看，就不担心保密的问题，反正就算你跟你的同胞说了，他们也不会相信你的，哈哈，这是最妙的部分啊！不过你也够幸运啦，没有几个中国人见识过这个产品的！多说无用，你自己体验一下就明白了。”他打转向灯，从大学路出口驶出101高速。&lt;/p&gt;

&lt;p&gt;车没有在宜家的停车场里停下，而是径直开到了停车场底层的一个地下通道，不知道检测了一下什么东西，封闭的大门缓缓打开，黑色的特斯拉电动汽车慢慢驶入。车子停稳，我跟着前辈走向一扇玻璃门，门口站着两个穿着警服但是没拿甜甜圈所以我也不确定究竟是不是警察的人。他们看了我一眼，然后冲前辈点了点头，什么也没说就把视线移到了别处。前辈示意我跟上，进门前一扬手佯作扔给了我一个什么东西，我下意识地伸手接了一下，然后才反应过来什么都没有，我有点儿莫名其妙地看了他一眼，他模仿着《黑客帝国》里面墨菲斯的口吻说了一句：“吞下这个红色的药丸……”&lt;/p&gt;

&lt;p&gt;如果是恶作剧的话，戏还做得真足。&lt;/p&gt;

&lt;p&gt;和《黑衣人》中的剧情一样，进了玻璃门，走廊里坐着一个根本不屑看你一眼的黑人老头。我跟着前辈径直走进直冲着大门的电梯，摁下里面唯一的一个按钮后，电梯迅速下降。&lt;/p&gt;

&lt;p&gt;等电梯门再次打开的时候，我霎时明白这绝对不是一个恶作剧了，因为，没有人会花这么大的成本来戏弄我。&lt;/p&gt;

&lt;p&gt;我无法准确地形容这个地方——一个巨大的圆形空间，毋庸置疑是在很深的地底，因为我看到电梯的竖井从高处的天花板直接下垂到地面。嗯，看起来这里像是一个大型数据控制中心，到处都是控制台以及计算机服务器——哦，我猜那应该是计算机服务器吧，尽管尺寸比我印象中的要大许多许多，不过毕竟在习惯了远程使用亚马逊提供的专业云计算服务之后，我已经很久没有见过真实的服务器到底长什么样子了。&lt;/p&gt;

&lt;p&gt;远处还有几个噪音和体积都很可观的奇怪装置，我的第一反应是大型强子对撞机或者粒子加速器，虽然我只在图片上见过它们长什么样子。我瞥见一些仪器的商标是洛克希德马丁或安捷伦科技，但更多的商标我则从来都没有见过。我清楚地记着自己当时的感觉——竭尽全力保持呼吸顺畅脚步平稳眼神坚定，就好像这些东西都是每天司空见惯的一样，但是心跳，则丝毫不加掩饰地表露着我无比兴奋又夹杂恐惧的心情，我没细数，但每分钟一百次绝对应该算是下限了。&lt;/p&gt;

&lt;p&gt;电梯的竖井看起来位于这座圆形地下控制室的圆心位置，我跟着前辈的步伐，穿过各种巨大的仪器和装置，来到了控制室的边缘，一个看起来像是标准宜家货运电梯的门口。&lt;/p&gt;

&lt;p&gt;“嗨，”前辈向货梯门口几个穿着宜家客户服务工作服、手持各种设备的人点点头打了个招呼，然后指了指我说，“我朋友，北京来的，带他领略一下飞路粉。”&lt;/p&gt;

&lt;p&gt;那几个人友好地冲我笑了笑，其中一个皮肤特别白皙、留着淡金色齐肩卷发的小伙子还同我握了握手，操着标准的加州口音说：“噢，北京？想回家看看吗？”&lt;/p&gt;

&lt;p&gt;“啊，你好，呵呵，当然想了……”我礼貌性地笑了笑，正在琢磨着满腹的疑问怎么开口，这时，前辈已经迈步走进缓缓打开门的货梯，然后冲我挥了挥手。我无奈地耸耸肩，打住了就在嘴边的问题，跟着前辈走进了货梯。&lt;/p&gt;

&lt;p&gt;在货梯门缓缓关上的时候，那个金发小伙子冲我们眨了眨眼，说了句：“一会儿见，等你们从北京回来！”&lt;/p&gt;

&lt;p&gt;货梯门缓缓关闭，开始平稳地向上驶去，瑞典肉丸的宣传画旁边是宜家家居那个著名的客户服务海报，你知道，就是那个可爱又诡异地张开双臂的小心脏。&lt;/p&gt;

&lt;p&gt;嗡……货梯停了下来，门缓缓打开，刚才的灯火通明已经消失得无影无踪，取而代之的是一片在我意料之外的黑暗。&lt;/p&gt;

&lt;p&gt;我狐疑地看了看前辈。&lt;/p&gt;

&lt;p&gt;“请吧。”他说，然后做了一个请的手势。&lt;/p&gt;

&lt;p&gt;我走出电梯，眼睛慢慢适应了黑暗，可以依稀看到这也是一个类似的控制室，各种仪器的指示灯在远处不停地摇曳和闪烁着。几个在大厅另一端似乎是值班的人抬起头看了看我们，然后挥了挥手，就继续把头埋在了巨大的监视器后面。&lt;/p&gt;

&lt;p&gt;“这边走。”前辈冲远处那几个人挥手打了个招呼之后，向左边走去。&lt;/p&gt;

&lt;p&gt;我紧跟在他的后面，心怦怦地跳着，脑中似乎预见到将要发生什么，但是又被自己想法的荒谬和无稽搞得惴惴不安。&lt;/p&gt;

&lt;p&gt;前辈推开一扇沉重的防火门，一阵凉风迎面吹来，转眼，我们站在了一栋建筑屋顶的室外防火梯顶端，头顶是被雾霾笼罩着的看不到繁星的夜空，眼前则是一条熟悉的高架桥，脚下这个蓝色的建筑上赫然挂着几个黄色的大字，虽然由于角度关系我并不能完全看清楚，但是我确凿地知道上面写的是什么。&lt;/p&gt;

&lt;p&gt;Holy shit，我们此刻站在北京东四环边上的宜家家居楼顶！&lt;/p&gt;

&lt;p&gt;前辈冲瞠目结舌的我笑了笑，“欢迎来到魔法世界，现在我给你呈上……”他低头看了看表，然后完成了这句话，“明天凌晨4点钟的北京！”&lt;/p&gt;

&lt;p&gt;我不知道我这种完全傻掉了的表情维持了多久，直到前辈拍了拍我的肩膀，“怎么样，麻瓜有什么问题要问吗？”&lt;/p&gt;

&lt;p&gt;我拙劣的文笔让我没有办法将我当时的心情恰如其分地表达出来——怎么说呢，就好像当了一辈子被万有引力束缚的人，一觉醒来之后却突然发现自己变成了一只甲虫，对这个世界所有的认知在刹那间被彻底颠覆，然后醍醐灌顶般领悟到，原来宇宙中最最重要的物理规则是能让自己在水面上自由行走而不会掉下去的表面张力啊，至于重力，见鬼，应该算是宇宙中最无关紧要的东西了吧！&lt;/p&gt;

&lt;p&gt;我当然不会愚蠢到会像一只甲虫一样从宜家家居的楼顶飞下去，毕竟，我是一个理性的人，我坚信这个世界上没有魔法，如果我无法理解这一切，那一定是我的认知能力不够而已。于是我从卡夫卡状态切换回来，扭过头望着前辈，然后把我一路上的猜测、疑惑和不解融合成了一句话：“你们是怎么做到的？”&lt;/p&gt;

&lt;p&gt;“哈哈，解密黑魔法的时刻到了。”他踱步到我前面，望着空旷的四环主路，将身体前倾，半倚着栏杆，然后缓缓地点燃了一支烟。&lt;/p&gt;

&lt;p&gt;我一语不发地注视着他每一个细微的举动，因为我知道接下来听到的每一句话，都将彻底地改变我的世界观。&lt;/p&gt;

&lt;p&gt;“让我们从波粒二项性这个最熟悉的话题谈起吧——我希望你的高中物理老师给你讲过这一段历史。”他吸了一口烟，掸落了些许烟灰，“现在想一想，一个能让牛顿、麦克斯韦、赫兹、汤姆逊、爱因斯坦、康普顿、德布罗意这些伟大的头脑为此争论不休的话题，注定会有一个不可思议的结局。”&lt;/p&gt;

&lt;p&gt;前辈用了一串人类历史上光辉不朽的名字开场，想必这会是一个不凡的故事吧，我想。&lt;/p&gt;

&lt;p&gt;“从光开始，双缝实验和麦氏理论揭示出其波动性，光电效应和康普顿效应又清晰地证明了其粒子性，而就在这一场论战还烽烟四起未见分晓时，20世纪初的量子革命又把电子推到了这场争论的风口浪尖。”他沉默了一小会儿，似乎在酝酿着什么，“玻尔的跃迁，原子光谱，海森堡矩阵，差点就把电子的粒子性盖棺定论了，但天晓得薛定谔从哪儿搞出了那套方程，居然离奇地全面翻盘，重新把波动性的标签贴回了电子身上。然后就有了让全世界物理学教授都头疼得要命的EPR悖论（爱因斯坦-波多尔斯基-罗森悖论）以及薛定谔那只著名的猫。”&lt;/p&gt;

&lt;p&gt;他回头看了我一眼，确定我依旧在跟着他的思路之后，他吸了口烟，继续说道：“然后这帮天才给了我们这样一个解释，当我们不去看那个该死的电子时，它便像一个幽灵一般按照波函数向四周发散开去，虚无缥缈的概率波严格地按照薛定谔波动方程的指使飘浮在空间里，但见鬼的是，当你睁开眼睛去看它的时候，幽灵就突然消失了，波函数立刻按照那时候的概率分布坍塌，其他地方的概率统统变成0，而电子则好整以暇地出现在一个点上，此处概率则为百分之一百，呵呵，这就是所谓的概率波‘坍塌’，哥本哈根学派那帮人这个词用得倒真是很形象。”他耸了耸肩。&lt;/p&gt;

&lt;p&gt;我虽然不精通量子物理，但硬核科幻小说还是看过几本的，对这些著名的量子物理学理论自然也明白其大概的意思，但我实在想象不出这些写在全世界每一本高等物理课本中的东西，和我们刚刚经历的不可思议的时空穿梭有什么关系。&lt;/p&gt;

&lt;p&gt;没等我抛出问题，前辈转过身来看着我，指着身后天空中朦胧的半轮月亮说：“按照他们的解释，如果我们转过头不去看月亮，组成月亮的这么一大堆粒子就会按照波函数弥散开去，但是只要你一回头，那一轮明月就又完好如初地悬挂在空中，似乎什么都没有发生过一样……”他把烟蒂掐灭，指着身后月亮的方向，笑着问，“杰克，她还在吗？”&lt;/p&gt;

&lt;p&gt;我被他的幽默逗笑了，于是说：“其实哥本哈根学派的鼻祖在东方，一个15世纪的中国哲学家曾经说过一句有名的话：‘你若未观测此花，此花并未真实地存在，按波函数而归于寂；你来观测此花时，则此花波函数发生坍缩，它的颜色一时变得明白起来。’”&lt;/p&gt;

&lt;p&gt;“噢？真的？他说花按照波函数发生坍塌？”前辈有点不可思议地扬了扬眉毛。&lt;/p&gt;

&lt;p&gt;“差不多吧，你知道他说的是古汉语啦……”我含混其词。&lt;/p&gt;

&lt;p&gt;“中国的古代哲人真是了不起啊……”前辈啧啧作叹，“嗯，不管怎样，这种解释遇到了两个致命的问题，第一就是波函数坍塌的原因。按照哥本哈根学派的解释，即‘观测者’的意识造成了波函数的坍塌，那么如何去定义‘观测者’呢？想必你听说过‘薛定谔的猫’吧。”&lt;/p&gt;

&lt;p&gt;我没有打断他，心中倒是默默地想起了刘慈欣的那本《球形闪电》。&lt;/p&gt;

&lt;p&gt;“即便假设哥本哈根学派的解释是对的，”他继续说道，“那么，如果有两个从某个大粒子衰变而来的小粒子向相反的方向飞去，在我们没有观察它们之前，这两个粒子的自旋则应该都处在一种左/右均有可能的概率叠加当中，但若我们突然观察粒子A，则它的波函数就在一瞬间坍塌了，比如说，它选择了‘左’旋，那么由于两个粒子总体要守恒，则粒子B肯定就是‘右’旋了。同时呢，量子论的概率解释告诉我们，粒子A选择‘左’是一个完全随机的决定。那就奇怪了，假设当我们在观察A的时候，这两个粒子已经间隔了好几万光年这么远的距离，那么粒子A选择‘左’旋的决策是如何被以超光速的速度传送给粒子B，使得粒子B能够按照粒子A选择‘左’旋的这个抉择发生相应的坍塌而选择‘右’旋呢？你听明白了吗？”&lt;/p&gt;

&lt;p&gt;我点了点头，我很感谢他能把这些困扰着无数量子物理学天才几十年的复杂问题讲述得如此浅显易懂。&lt;/p&gt;

&lt;p&gt;“北京真冷。”他把手插到口袋里，远处四环主路的路灯熄灭，已经有零星的行人和车辆伴随着路边的清洁工人开始和巨大的城市一起，慢慢苏醒过来。&lt;/p&gt;

&lt;p&gt;“还好，我们就快要讲到最关键的部分了，我得快点儿讲，下午还有一个会呢……”他扔掉第二支烟。&lt;/p&gt;

&lt;p&gt;我点点头，继续倾听着。&lt;/p&gt;

&lt;p&gt;“因为哥本哈根关于波函数坍塌的这种解释带来了太多复杂的问题，于是一个叫做休·埃弗莱特的伟大物理学家提出了另外一种猜测——你有听说过休·埃弗莱特吗？没有？太遗憾了。不过没什么，再过一百年，估计这会是全世界所有历史课本上最重要的名字之一了。”前辈脸上露出了一丝遗憾的表情。&lt;/p&gt;

&lt;p&gt;“不管怎样，他的观点是，双缝实验中电子的波函数无需坍塌，而是继续保持左/右的叠加状态——当然，所有人都知道这和人们在现实世界中观测到的现象不符，但埃弗莱特的解释很大胆，他说当电子穿过双缝后，处于叠加状态的不仅仅是电子，还包括我们整个的世界！也就是说，当一个电子穿过双缝后，出现了两个叠加在一起的世界，其中的一个世界里，这个电子穿过了左边的缝隙；而在另一个世界里，这个电子则通过了右边的……”前辈笑着摇摇头，似乎到现在为止也不愿相信。&lt;/p&gt;

&lt;p&gt;“这就是埃弗莱特在上世纪50年代论文中提出的多世界解释。听起来很疯狂是不是？就因为一个电子，宇宙就多了一个！当然，它的优势显而易见，比如说薛定谔的猫再也不必为死活问题而困扰了——宇宙分裂成了两个就解决了问题，在一个宇宙里猫是活的，而在另一个宇宙里，猫直接就死翘翘了，不用等到观测者打开箱子让放射性粒子坍塌的那一刻。但它的劣势则更明显了，你大概也想到了，这个理论的成本未免也太大了一点，仅仅因为一粒电子在双缝实验中选择从左走还是从右走，我们就得多赔上一个世界……自然，埃弗莱特的理论因为上述的这个缺陷，在当时并未受到学术界的重视，而他本人更是逐渐退出了物理界，创立了著名的Lambda公司。唉，很多事就是这样，总是要等到多年以后回头再望时，经过重重的历史迷雾，你才会意识到曾经发生过的这些事情究竟有多么伟大。”说到这里，前辈自我解嘲地耸耸肩，笑着说，“唉，也许这就是我们和天才的区别吧……”&lt;/p&gt;

&lt;p&gt;我没有说什么，在清晨的凉风中，我突然感到了一种苍白的无力感和渺小感。&lt;/p&gt;

&lt;p&gt;“简单说一下多宇宙的概念。”前辈收拾了一下感慨的心情，“拿我们都很熟悉的二维笛卡尔平面来举例好了。在这样一个平面系统里，任何一个点都可以用一个包含两个变量的坐标（x，y）来表示，比如（1，2），这两个数字分别代表该点在x轴和y轴上的投影。同理，一个包含三个变量的坐标就可以描述一个三维空间中的点，而这三个变量分别代表该点在三个互相垂直的维度方向的投影。”前辈看了我一眼，做出一个“听懂了吗”的询问表情。&lt;/p&gt;

&lt;p&gt;我点点头予以回应。&lt;/p&gt;

&lt;p&gt;前辈缓缓抬起头，看着北京初秋渐渐泛出曙光的苍穹，放慢语速说道：“假设我们是一种没有维度的‘质点人’，我们的生命体就是一个点，而且只能在一个维度上做直线运动，这么说吧，我们这群‘质点人’生活的世界就是笛卡尔平面坐标系中的x轴，我们能感知到这条直线上的东西，而对别的一无所知。让我们再假设真实的宇宙是一个悬在二维平面上的点，比如矢量（1，2）好了，那么对于生活在x轴上的我们来说，我们对真实宇宙的感知只是其在x轴上的投影1而已，我们完全不知道其实真实的宇宙还有一个长度为2的y轴投影。假设有另外一群和我们一样的质点人生活在y轴上，同样，他们对真实宇宙的感知则只有投影在他们世界里的那个2而已。又因为我们生活的x轴世界和他们生活的y轴世界相互垂直，所以两个世界之间没有任何投影，因此我们完全不知道对方世界的存在，而且都偏执地认为自己生活的世界是真实的宇宙本身。其实呢，有幸生活在三维空间中的我们可以清楚地看到，这个真实的二维宇宙其实是x世界和y世界两个的叠加。”前辈的视线从苍穹转开，看着我露出恶作剧的笑容，说，“我们的宇宙也是如此。”&lt;/p&gt;

&lt;p&gt;我还来不及错愕，前辈继续说了下去：“最新的物理学研究表明，我们真实的宇宙是一个存在于非常高维的希伯特空间命名，在量子力学中，一个物理系统可以表示为一个复希尔伯特空间，其中的向量是描述系统可能状态的波函数中的一个矢量，和刚才那个例子一样，这个高维空间是由无数个低维世界所构成的，而每个低维世界都只能感受到真实宇宙的矢量在其中的投影而已，所以，对于每个世界而言，宇宙都不相同，而宇宙波函数则是严格按照薛定谔方程演化的叠加状态。”前辈停了下来，一脸郑重其事的表情说，“截至这里，是发展中国家所认知的物理学，而接下来是真正疯狂的事情。”&lt;/p&gt;

&lt;p&gt;天哪，我吐了吐舌头，敢情这些都是铺陈而已啊。&lt;/p&gt;

&lt;p&gt;“之前的物理学界认为，由于真实的宇宙存在于一个非常高维的空间，比如说1000亿维空间，那么假如我们生活的世界是四维的话，那它们之间则几乎必定是垂直的了，因此物理学家们认为我们的世界无法感知到其他的世界。”他笑了笑，“如你所愿，这里会有一个大大的转折——在2000年斯隆数字巡天（Sloan Digital Sky Survey）项目启动后，新墨西哥州的望远镜在短短几周内不仅收集到比天文学历史上总共收集的数据还要多得多数据，更带给了物理学家惊人的发现——是的，我们看到了其他世界在我们世界的投影。”&lt;/p&gt;

&lt;p&gt;我的嘴已经合不拢了，所有的科幻片都加起来也不及刚才这句话给我带来的感官冲击强烈。&lt;/p&gt;

&lt;p&gt;“当然，我们能探测到和计算出的宇宙还局限于在家谱树上离我们较近的那些——大概过去几十天分裂出去的其他分支而已，对于更早分裂出去的宇宙，我们则还一无所知。但是，既然已经证实多维宇宙的存在的理论为真，那么，了解那些从遥远的时代就和我们这个世界分道扬镳的宇宙则就都变成了单纯的技术问题，预计2016年在智利投入使用的大型视场全景巡天望远镜（Large Synoptic Survey Telescope）大约能让我们定位几百年前分裂出去的宇宙，在其中的某些宇宙中，也许哥伦布并没有发现美洲，或者拿破仑在滑铁卢之战中大获全胜呢……倘若我们有朝一日能突破140亿光年的视界，或许我们能找到更遥远时代就分裂出去的宇宙也说不定，真想知道6500万年前那颗陨石没有落到墨西哥湾的那个宇宙现在是什么样子啊……”前辈眼里充满了对未知的那种渴望和希冀。&lt;/p&gt;

&lt;p&gt;“嗯，你说的我大概明白了，但我还是好奇，这个理论和你们将我从加州隔空传送（我用的词是teleport，实在想不出更准确的描述了）到北京有什么关系？”我觉得有必要刨根问底一下。&lt;/p&gt;

&lt;p&gt;“哈哈，好问题。不过，我要纠正你一下，我们并没有把你从加州送到北京（他用了send这个词），只是把你从‘杰克此刻在加州’的那个宇宙送到了‘杰克此刻在北京’的那个宇宙而已。换句话说，我们没有把生活在x轴世界上的你从5移动到10，而是把你直接从x轴移动到了y轴，而幸运的是，在那个y轴世界里，”他揶揄地指了指我，“杰克此刻本来就在10，明白了吗？”&lt;/p&gt;

&lt;p&gt;“从‘杰克此刻在加州’的那个宇宙送到了‘杰克此刻在北京’的那个宇宙？好吧，我先不管你们是怎么做到这个的，我的问题是，那个之前生活在这个‘杰克此刻在北京’的宇宙中的杰克，现在怎么样了呢？”我心里有点儿莫名的不安了。&lt;/p&gt;

&lt;p&gt;“当然是正在和我说话啊！”前辈大笑起来，“确切地说，‘杰克此刻在北京’的那个宇宙在我们走出电梯的那一刹那发生了分裂，宇宙1中杰克依然在北京，但全然没有听过刚才我的那番长篇大论；而在宇宙2中，杰克不但在北京，而且刚刚被我的一番话所吓倒。等我们一会儿坐电梯离开的时候，宇宙2则继续分裂，一个变成杰克在北京没有离开的宇宙2.1，另一个变成杰克从北京消失了的宇宙2.2。当然，至于那个杰克从北京莫名消失的宇宙将何去何从，我们就不在乎了，毕竟还有那么多杰克压根儿就没有存在过的宇宙，对吧？”&lt;/p&gt;

&lt;p&gt;“听起来像是你们找了一个符合一定要求的平行宇宙，比如‘杰克此刻在北京’这个宇宙，然后像Unix系统中调用fork命令一样复制了这个宇宙，再把我当做信号量传了过来？那我的亲人和朋友呢？他们在这个宇宙中还存在吗？”我突然感到有点儿恐惧。&lt;/p&gt;

&lt;p&gt;前辈拍了拍我肩膀，“别担心，杰克，只要我们一会儿再回到来时的那个宇宙，那么，你的意识、记忆、感情，以及你朋友的意识、记忆和感情，都将没有任何变化。当然了，这么说也有点儿不对，毕竟在我们离开的这段时间里，我们来的那个宇宙已经发生了亿万次的分裂，确切地说，我们回去的只是那个宇宙亿万次分裂中的一个分支，毕竟，先哲说得好，一个人是无法两次踏进同一条河流的嘛……”前辈耸耸肩，“不过你放心，这亿万个宇宙之间的差别微乎其微，就像是纽约爱乐乐团录制的两张《命运交响曲》唱片一样，第一张里小提琴手在某一小节心血来潮地加了一段华彩，而第二张里没有，但谁也不能否认这两张唱片都是《命运交响曲》，对吧？”前辈轻松地笑了笑。&lt;/p&gt;

&lt;p&gt;我感觉自己的脑细胞似乎无法再追问下去了，“好吧，最后一个问题，这些东西关宜家什么事儿？”我实在是好奇这个。&lt;/p&gt;

&lt;p&gt;“哈哈哈哈……”前辈爽朗地笑了，“你倒想想看，若没有宜家做伪装，我们那些大型的仪器和装置放到什么地方去？另外，若是每天有一千多个来自世界各地的人凭空地在北京某个地方集体出现，你们北京人民还不得第一时间报警啊！当初宜家在北京选址时也充分考虑了这一点，这里离各国的使馆区都近，本来外国人就多，人们也就见惯不怪了，一千多人按照泊松分布出现在这里，没有人会觉察到异样的。”&lt;/p&gt;

&lt;p&gt;“每天一千个外国人用这种方法往返于北京和全球各地？”我惊诧居然没有任何人产生丝毫的怀疑。&lt;/p&gt;

&lt;p&gt;“对啊，所以你明白这项技术为什么迟迟不能被公开了吧。试想一下，如果这项技术落到了恐怖分子或者大毒枭手里……”前辈做了一个鬼脸，看了看表，示意我俩该回去了。&lt;/p&gt;

&lt;p&gt;“啊……好吧……倘若这项技术有朝一日能够被公之于众的话，那可真是时空的一场革命了，估计全球的客运海运公司就都得倒闭了……”我惊诧地说，跟在他后面往回走。&lt;/p&gt;

&lt;p&gt;“何止如此啊，偷渡问题从此之后就不止是在国境线严查死守了，这将彻底改变整个世界的地缘政治格局啊……”前辈忧心忡忡，顺便挥手向控制室里的几个人致意。&lt;/p&gt;

&lt;p&gt;“唉，对了，这个项目是什么时候开始的？”我俩踏进货梯。&lt;/p&gt;

&lt;p&gt;“哈哈，这个你应该比我清楚啊，北京新的宜家家居什么时候建成的？”&lt;/p&gt;

&lt;p&gt;前辈关上货梯门，“过去七年里，大概有超过一百五十万人次从发达国家通过宜家来往于北京和世界各地吧，而且我听说很多人都在北京置办了家业，你知道，金融危机之后，很多人想通过在第三世界花美元来降低自己的生活成本……”&lt;/p&gt;

&lt;p&gt;我仿佛突然明白了为何北京的房价和人民币汇率从2006年开始如此狂飙的原因了。&lt;/p&gt;

&lt;p&gt;货梯门打开，那个淡金色头发的哥们儿走过来，冲我们笑着说：“欢迎回来！”不知道是否是错觉，我总觉得他的头发颜色变深了，我是说，和我们踏上电梯前那个宇宙中的他相比。&lt;/p&gt;

&lt;p&gt;后来前辈送了我一张宜家飞路粉产品的会员卡，这就意味着我也可以使用宜家飞路粉来做世界旅行了。&lt;/p&gt;

&lt;p&gt;我和老婆商量之后，在2010年6月搬回了北京，虽然空气差了点儿，但毕竟生活更方便一些。我每天晚上11点都要去东四环宜家坐货梯班车到帕罗奥图，然后走101高速赶在当天早晨9点前去公司上班，我太太则辞掉工作，开了一家快递公司——虽然物品大小有严格要求，但是快速的投递时间和低廉的价格却有绝对优势。从2010年开始，每个周末我俩基本都不在家，而是去把全球有宜家的地方都逛了个遍——若不用考虑旅费和住宿的话，环球旅行其实真的不贵。&lt;/p&gt;

&lt;p&gt;2012年是一个特殊的年份，便携式飞路粉被研制出来，也就是说，平行世界旅行在没有宜家的宇宙中也可以进行了，这就意味着，去一个几千年，甚至几万年前就和我们当前宇宙分裂的宇宙中旅行，不再是一个幻想了。&lt;/p&gt;

&lt;p&gt;前辈对此兴奋不已——他之前总是为自己生活在一个已经基本没有未知死角的世界里感到惋惜，常常抱怨没有机会去参加真正的冒险，在得知便携式飞路粉推出的时候，他在第一时间去了一个五百年前分裂出的宇宙中冒险，回来后如痴如醉地对我说：“杰克，你小时候读过凡尔纳的小说吗？你有幻想过有一天能去一个完全陌生的世界里冒险的那种刺激吗？那是真正的未知世界啊，你想知道1492年哥伦布没有发现美洲的那个世界是什么样子的吗……”&lt;/p&gt;

&lt;p&gt;在前辈各种离奇故事的感染下，我和老婆终于被他的怂恿打动了，决定也要尝试一下这种诡异的旅行——唉，也许当初离开家来美国求学的事实，就证明了渴望看到更多世界的好奇心早就在我们的DNA里了。当然，这种旅行是有风险的——除了未知宇宙中种种无法预测的环境外，这么远的平行宇宙间信号量传递会有更大的误差，也就是说，即便一切顺利，我们也可能回到一个和出发时那个宇宙差别巨大的分支，拿前辈的话说，一盘再高保真的唱片，在被翻录过亿万次之后，听起来肯定会和第一张大相径庭，比如，据他说，他记忆中的我们就和眼前的我们有诸多的不同……&lt;/p&gt;

&lt;p&gt;不过怎么形容呢，就像在大航海时代被各种未知世界中意想不到的事情深深吸引的冒险家一样，虽然明明知道踏上那艘三桅帆船后，可能遭遇的命运除了发现新世界之外，也可能是葬身鱼腹，或流落荒蛮，但无法抑制的好奇心却总是占据上风，大概，这是所有冒险家的通病吧。&lt;/p&gt;

&lt;p&gt;今天是2013年6月28日，我们终于决定要踏上旅途。目标宇宙在一千年前与我们所在的宇宙发生分裂，据那些去过的人回来说，那是一个十字军东征大获全胜、文艺复兴提前两百年发生、全球信仰天主教的宇宙，还建议我们带上《古兰经》作为纪念品给那里的人们——据说那个宇宙里的学者只在历史文献的只言片语中听说过《古兰经》的名字，而从未亲眼见过……我希望，这会是一次极为有趣的冒险。&lt;/p&gt;

&lt;p&gt;P.S.不知道能不能够再回到这个宇宙中，所以，决定先将这篇文章发在博客上，等旅行回来后再做更新。&lt;/p&gt;

&lt;p&gt;P.S.S.不管你相信也好，不信也好，能在这个宇宙中认识你们，真好。&lt;/p&gt;
</description>
        <pubDate>Thu, 21 May 2020 00:00:00 +0800</pubDate>
        <link>https://donothing.site/2020/05/21/science-fiction-world-201403000/</link>
        <guid isPermaLink="true">https://donothing.site/2020/05/21/science-fiction-world-201403000/</guid>
        
        <category>美文</category>
        
        
        <category>美文收录</category>
        
      </item>
    
      <item>
        <title>Linux 中的 netcat 网络工具简介</title>
        <description>&lt;p&gt;&lt;code&gt;netcat&lt;/code&gt; 是 Linux 系统中的网络工具，其通过 TCP 和 UDP 协议在网络中读写数据。如果与其他工具结合，以及加上重定向功能，还可以实现很多不同的功能。所以其以体积小功能灵活而著称，可以用来做很多网络相关的工作。Posix 版本的 netcat 主要有 GNU 版本和 OpenBSD 两种，都可以在 debian/ubuntu 系统下面安装，但 Windows 系统下则只有 GNU 版本的。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nc&lt;/code&gt; 命令行工具即是 Linux 系统下的 netcat 工具。在 debian/ubuntu 系统下，可以通过如下命令查看其版本：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;readlink -f $(which nc)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;大致可以得到以下两种结果：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;/bin/nc.traditional:&lt;/strong&gt; 默认 GNU 基础版本，一般系统自带&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;/bin/nc.openbsd:&lt;/strong&gt; OpenBSD 版本，强大很多&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;不管是 GNU 版本还是 OpenBSD 版本，都有新老的区别。主要区别是，传送文件时 stdin 发生 EOF 了时，老版本会自动断开，而新的 GNU/OpenBSD 还会一直连着。&lt;/p&gt;

&lt;h3 id=&quot;part-2c9a35823bb502fe&quot;&gt;常用参数&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;netcat&lt;/code&gt; 使用的基本形式为：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;nc 参数 目的地址 端口
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;常用的参数说明如下：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;-k  在当前连接结束后保持继续监听
-l  用作端口监听，而不是发送数据
-n  不使用 DNS 解析
-N  在遇到 EOF 时关闭网络连接
-p  指定源端口
-u  使用 UDP 协议传输
-v  (Verbose)显示更多的详细信息
-w  指定连接超时时间
-z  不发送数据
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;以下列举一些常用的实例：&lt;/p&gt;

&lt;h3 id=&quot;part-2db919e3b16bfc0f&quot;&gt;端口测试&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;netcat&lt;/code&gt; 可以替代 telnet 工具来测试远程注意端口是否打开，如命令：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;telnet 192.168.1.8 8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;可以用 nc 来代替：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;nc -vz 192.168.1.8 8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;还可以同时指定多个端口或者一个端口范围&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;nc -v -z -w 3 192.168.56.1 22 80 8000 8080

nc -v -z -w 3 192.168.1.8 8080-8088
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;part-2ed6b0952b18f4f5&quot;&gt;连接测试&lt;/h3&gt;

&lt;p&gt;如果在主机上配置了防火墙，想要测试一下开放的端口是否可以与外界联通，可以用 netcat 监听该端口，然后从外界尝试连接。&lt;/p&gt;

&lt;p&gt;在主机上执行：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;nc -l -p 8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;注意，OpenBSD 版本 netcat 用了 -l 以后可以省略 -p 参数，写做：nc -l 8080 ，但在 GNU 版本的 netcat 无法运行，所以推荐写法是都加上 -p 参数，这样两个版本都通用。&lt;/p&gt;

&lt;p&gt;在其它主机上可以尝试连接以上主机打开的端口：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;nc 192.168.1.8 8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;如果两台主机能够正常连通的话，就如同打开了一个聊天室，可以相互发送数据并显示。注意，老版本的 netcat 只要 CTRL+D 发送 EOF 就会断开，新版本一律要 CTRL+C 结束，不管是服务端还是客户端只要任意一边断开了，另一端也就结束了，但是 OpenBSD 版本的 netcat 可以加一个 -k 参数让服务端持续工作。&lt;/p&gt;

&lt;p&gt;可以通过如下方式给 “聊天室” 消息加上一个简单的前缀：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;# Server 端
$ mawk -W interactive '$0=&quot;Server: &quot;$0' | nc -l 8080
Client: Hello
Hi
Client: My name is Huoty

# Client 端
$ mawk -W interactive '$0=&quot;Client: &quot;$0' | nc localhost 8080
Hello
Server: Hi
My name is Huoty
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这里就有一个使用 netcat 实现的简单聊天室脚本：&lt;a href=&quot;https://github.com/Aeres-u99/ncChat&quot;&gt;Aeres-u99/ncChat&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;udp&quot;&gt;测试 UDP&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;netcat&lt;/code&gt; 工具可以指定使用 UDP 协议传输数据，只需家还是那个 &lt;code&gt;-u&lt;/code&gt; 参数即可。如下则是使用 UDP 方式监听 8080 端口：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;nc -u -l -p 8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;连接主机时也可以指定 UDP 方式：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;nc -u 192.168.1.8 8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;part-2c8cade5c77d9b56&quot;&gt;文件传输&lt;/h3&gt;

&lt;p&gt;如何两台主机间想要传输文件，而又不能使用 scp/szrz 等工具时，则可以用 netcat 代替。在需要接受文件的主机上执行：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;nc -l -p 8080 &amp;gt; test.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后再另一台主机上向其传输文件：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;nc 192.168.1.8 8080 &amp;lt; test.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;注意，老版本 GNU/OpenBSD 的 netcat 在文件结束（标准输入碰到 EOF），发送文件一端就会关闭连接，而新版本不会。这可能就需要再开个窗口到接收文件的主机上看看接收下来的文件是否已经完整。当传输完成后，再在任意一端 CTRL+C 结束连接。对于新版 OpenBSD 的 netcat 有一个 -N 参数，可以指明 stdin 碰到 EOF 就关闭连接（和老版本一致），如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;/bin/nc.openbsd -N 192.168.1.8 8080 &amp;lt; test.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;其实 GNU 版本的 netcat 也有可以加个 -q0 参数，达到和 OpenBSD 版本 -N 的效果：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;/bin/nc.traditional -q0 192.168.1.8 8080 &amp;lt; test.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;此外，也可以用 pv 命令来查看文件传输的进度。&lt;code&gt;pv&lt;/code&gt; 命令即 &lt;strong&gt;Pipe Viewer&lt;/strong&gt;，意思是通过管道显示数据处理进度的信息。其甚至可以用来代替 cp 命令拷贝文件：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ pv ~/Downloads/test.png &amp;gt; ~/Temp/test.png
 656KiB 0:00:00 [ 267MiB/s] [==================================&amp;gt;] 100%
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;于是，使用 netcat 来做文件传输时，可以使用 pv 来显示传输的进度：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;# 传输端
pv test.txt | nc 192.168.1.8 8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;甚至还可以传输一个目录：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;# 服务端
tar -zcf - debian-10.0.0-amd64-xfce-CD-1.iso  | pv | nc -l -p 8080

# 客户端
nc 192.168.1.8 8080 | pv | tar -zxf -
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;如何对传输的数据不放心，还可以进行加密，如使用 mcrypt 工具加密数据：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;# 服务端，使用 mcrypt 工具加密数据，需要输入密码
nc localhost 1567 | mcrypt –flush –bare -F -q -d -m ecb &amp;gt; file.txt

# 客户端，使用 mcrypt 工具解密数据，需要输入密码
mcrypt –flush –bare -F -q -m ecb &amp;lt; file.txt | nc -l 1567
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;part-2b7d4ba736fa87a7&quot;&gt;克隆设备&lt;/h3&gt;

&lt;p&gt;使用 netcat 可以用来对整个磁盘设备进行复制：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;# 服务端
dd if=/dev/sda | nc -l 1567

# 客户端
nc -n 182.168.1.8 | dd of=/dev/sda
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;dd&lt;/code&gt; 命令是一个从磁盘读取原始数据的工具，通过 netcat 服务器重定向它的输出流到其他机器并且写入到磁盘中，它会随着分区表拷贝所有的信息。如果多了分区，可以根据情况更改 sda 为 sda1, sda2 等等。&lt;/p&gt;

&lt;h3 id=&quot;http&quot;&gt;HTTP 服务器&lt;/h3&gt;

&lt;p&gt;用 netcat 可以实现一个简单的 HTTP 服务器，用以测试一些功能。首先，穿件一个简单地的 index.html 文件：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Test Page&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Serving this file using Netcat Basic HTTP server!&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后运行服务端：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;while : ; do ( echo -ne &quot;HTTP/1.1 200 OK\r\n&quot; ; cat index.html; ) | nc -l -p 8080 ; done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;http&quot;&gt;HTTP 客户端&lt;/h3&gt;

&lt;p&gt;用 netcat 也可以实现一个简单的 HTTP 服务器，用于请求 HTTP 数据。&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;printf &quot;GET / HTTP/1.0\r\n\r\n&quot; | nc donothing.site 80
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;part-2de6a062583fec66&quot;&gt;系统后门&lt;/h3&gt;

&lt;p&gt;GNU 版本的 netcat 有一个 &lt;code&gt;-e&lt;/code&gt; 参数，可以在连接建立的时候执行一个程序，并把它的标准输入输出重定向到网络连接上来，于是我们可以在主机上用 &lt;code&gt;-e&lt;/code&gt; 参数执行 bash 命令：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;/bin/nc.traditional -l -p 8080 -e /bin/bash -i
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;对于 OpenBSD 版本的 netcat，&lt;code&gt;-e&lt;/code&gt; 命令被删除了，但可以用管道来完成：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;mkfifo /tmp/f
cat /tmp/f | /bin/bash 2&amp;gt;&amp;amp;1 | /bin/nc.openbsd -l -p 8080 &amp;gt; /tmp/f
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这样在客户端主机上执行 &lt;code&gt;nc 192.168.1.8 8080&lt;/code&gt; 便可以连接上服务端主机的 bash 进行一些操作。这种方式有时候可以用来绕过防火墙的限制。&lt;/p&gt;

&lt;p&gt;以上列举的只是 netcat 工具使用示例一小部分。&lt;code&gt;netcat&lt;/code&gt; 就是在命令行以直接的方式操作 TCP/UDP 进行原始的：监听，连接，数据传输等工作。所以只要有足够的想象力，再搭配管道等其他工具，便可以实现许许多多灵活多样的功能，或者进行各种网络测试。&lt;/p&gt;

&lt;h3 id=&quot;part-2bb23717ee7e9bfc&quot;&gt;参考资料&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/83959309&quot;&gt;https://zhuanlan.zhihu.com/p/83959309&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tecmint.com/netcat-nc-command-examples/&quot;&gt;https://www.tecmint.com/netcat-nc-command-examples/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 03 Apr 2020 00:00:00 +0800</pubDate>
        <link>https://donothing.site/2020/04/03/linux-natcat/</link>
        <guid isPermaLink="true">https://donothing.site/2020/04/03/linux-natcat/</guid>
        
        <category>linux</category>
        
        <category>netcat</category>
        
        
        <category>Linux</category>
        
      </item>
    
      <item>
        <title>Linux 终端、作业控制、守护进程</title>
        <description>&lt;h2 id=&quot;tty&quot;&gt;终端(TTY)&lt;/h2&gt;

&lt;p&gt;一般意义上的终端（Terminal）是指人机交互的设备，也就是可以接受用户输入的并输出信息给用户的设备。在计算机刚出现时，终端是电传打字机（Teletype/Teletypewriter，即 TTY）和打印机，也即所谓的 &lt;strong&gt;物理终端&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;提到终端就不得不提到 &lt;strong&gt;控制台（Console)&lt;/strong&gt;。控制台的概念与终端含义极其相近，现今经常用它们表示相同的东西。但在计算机发展的早期，却是不同的东西。一些数控设备(比如数控机床)的控制箱，通常会被称为控制台。所以，最初的控制台就是一个直接控制设备的面板，上面有很多控制按钮。在计算机里，把那套直接连接在电脑上的键盘和显示器就叫做控制台。而终端是通过串口连接上的，不是计算机自身的设备，而控制台是计算机本身就有的设备。一个计算机只有一个控制台，但可以连接很多的终端。计算机启动的时候，所有的信息都会显示到控制台上，而不会显示到终端上。也就是说，控制台是计算机的基本设备，而终端是附加设备。计算机操作系统中，与终端不相关的信息，比如内核消息，后台服务消息，都可以显示到控制台上，但不会显示到终端上。控制台一般由系统管理员使用，用于管理整个计算机，而普通用户则通过终端连接到计算机进行使用。&lt;/p&gt;

&lt;p&gt;现在终端和控制台都由硬件概念，逐渐演化成了软件的概念。在现在的操作系统中，可以这样来理解控制台与终端：能直接显示系统消息的那个终端称为控制台，其他的则称为终端（控制台也是一个终端）。实际上，现在在使用 Linux 操作系统时，已经不区分控制台与终端了。因为控制台 (Console) 与终端 (Terminal) 的概念渐渐的模糊起来。在现代，键盘与显示器既可以认为是控制台，也可以认为是普通的终端。因为用户一般都对系统有很大的控制权，即可以作为普通用户，也可以作为系统管理员。所以现在的 Console 与 Terminal 含义基本一致。&lt;/p&gt;

&lt;p&gt;最初的终端是一种文本终端 (Text Terminal)，即 &lt;strong&gt;字符终端 (Character Terminal)&lt;/strong&gt;，只能接收和显示文本信息的终端。后来又发展出了 &lt;strong&gt;图形终端（Graphical Terminal）&lt;/strong&gt;，其不但可以接收和显示文本信息，也可以显示图形与图像。随着 GUI 的输出，使用传统意义上的终端的人也越来越少，逐渐被全功能显示器所取代。但 Linux 仍然保留了字符终端（实际上已经是图形终端了，只是在习惯上仍然较字符终端），通过快捷键 &lt;strong&gt;Ctrl+ALT+F1~F6&lt;/strong&gt; 可以进入到六个不同的字符终端。&lt;/p&gt;

&lt;p&gt;真正意思上的硬件终端已经消失，那么现代的操作系统是怎么与那些传统的、不兼容图形接口的命令行程序（如 GNU 工具集命令）交互的呢？因为这些程序无法直接读取键盘输入，也无法直接把结果输出到显示器上。所以现代的操作系统通过一个程序来模拟传统的终端行为，这个程序即 &lt;strong&gt;终端仿真器（Terminal Emulator）&lt;/strong&gt;，通常也叫做终端模拟器。对于命令行程序，终端模拟器会伪装成一个传统终端设备；而对于现代的图形接口，终端模拟器会伪装成一个 GUI 程序。&lt;/p&gt;

&lt;p&gt;一个终端模拟器的标准工作流程是这样的：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;捕获用户的键盘输入&lt;/li&gt;
&lt;li&gt;将输入发送给命令行程序（程序会认为这是从一个真正的终端设备输入的）&lt;/li&gt;
&lt;li&gt;拿到命令行程序的输出结果（STDOUT 以及 STDERR）&lt;/li&gt;
&lt;li&gt;调用图形接口（比如 X11），将输出结果渲染至显示器&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;目前，操作系统用户所使用的所谓终端，都是模拟终端。如 GNU/Linux 中的 gnome-terminal、Konsole；MacOSX 中的 Terminal.app、iTerm2；Windows 中的 Win32 控制台、ConEmu 等等。上面提到的，在 Linux 中可以 Ctrl+ALT+F1~F6 切换六个终端，其实这也不是传统意义上的终端了，它们也是终端模拟器的一种。这些全屏的终端界面与运行在 GUI 下的终端模拟器的唯一区别就是它们是由操作系统内核直接提供的。这些由内核直接提供的终端界面被叫做 &lt;strong&gt;虚拟控制台 (Virtual Console)&lt;/strong&gt;，而运行在图形界面上的终端模拟器则被叫做 &lt;strong&gt;终端窗口 (Terminal Window)&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;拥有控制终端的进程都可以通过一个特殊的设备文件 &lt;code&gt;/dev/tty&lt;/code&gt; 访问它的控制终端，进程认为 /dev/tty 就是它的控制终端。但事实上每个终端设备都对应一个不同的设备文件，/dev/tty 只是提供了一个通用的接口，一个进程要访问它的控制终端既可以通过 /dev/tty 也可以通过该终端设备所对应的设备文件来访问。可以用 &lt;code&gt;tty&lt;/code&gt; 命令来查看当前控制终端实际指向的设备文件。也可以通过 ttyname 系统函数由文件描述符查出对应的文件名，该文件描述符必须指向一个终端设备而不能是任意文件。如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fd 0: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ttyname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fd 1: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ttyname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fd 2: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ttyname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;在图形终端窗口下运行，结果如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;fd 0: /dev/pts/0
fd 1: /dev/pts/0
fd 2: /dev/pts/0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;在开一个终端窗口运行，结果则如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;fd 0: /dev/pts/1
fd 1: /dev/pts/1
fd 2: /dev/pts/1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;切换到字符终端 Ctrl-Alt-F1 运行，结果如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;fd 0: /dev/tty1
fd 1: /dev/tty1
fd 2: /dev/tty1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;每个不同的字符终端都对一个不同的设备文件，分别是 /dev/tty1~/dev/tty6。设备文件 &lt;code&gt;/dev/tty0&lt;/code&gt; 表示当前虚拟终端，比如切换到 Ctrl-Alt-F1 的字符终端时 /dev/tty0 就表示 /dev/tty1，切换到 Ctrl-Alt-F2 的字符终端时 /dev/tty0 就表示 /dev/tty2，就像 /dev/tty 一样也是一个通用的接口，但它不能表示图形终端窗口所对应的终端。&lt;/p&gt;

&lt;p&gt;程序执行时会自动打开三个文件：标准输入、标准输出 和 标准错误输出，其文件描述符分别为 0, 1, 2。默认情况下（没有重定向），每个进程的标准输入、标准输出和标准错误都指向控制终端，进程从标准输入读也就是读用户的键盘输入，进程往标准输出或标准错误输出写也就是输出到显示器上。在控制终端输入一些特殊的控制键可以给（前台）进程发送信号，如 &lt;code&gt;Ctrl+C&lt;/code&gt; 表示 SIGINT，&lt;code&gt;Ctrl+\&lt;/code&gt; 表示 SIGQUIT。&lt;/p&gt;

&lt;p&gt;用 tty 查看当前的终端设备文件，并用 lsof 查看该设备被那些进程打开：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ tty
/dev/pts/0
$ lsof /dev/pts/0
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
zsh     22773 huoty    0u   CHR  136,0      0t0    3 /dev/pts/0
zsh     22773 huoty    1u   CHR  136,0      0t0    3 /dev/pts/0
zsh     22773 huoty    2u   CHR  136,0      0t0    3 /dev/pts/0
zsh     22773 huoty   10u   CHR  136,0      0t0    3 /dev/pts/0
lsof    23297 huoty    0u   CHR  136,0      0t0    3 /dev/pts/0
lsof    23297 huoty    1u   CHR  136,0      0t0    3 /dev/pts/0
lsof    23297 huoty    2u   CHR  136,0      0t0    3 /dev/pts/0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;运行 tty 与 lsof 命令时，其与控制终端的交互流程：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;                   +--------------------------+    R/W     +------+
Input  -----------&amp;gt;|                          |&amp;lt;----------&amp;gt;| bash |
                   |          pts/0           |            +------+
Output &amp;lt;-----------|                          |&amp;lt;----------&amp;gt;| lsof |
                   | Foreground process group |    R/W     +------+
                   +--------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;程序执行时会自动打开三个文件：标准输入、标准输出 和 标准错误输出，其文件描述符分别为 0, 1, 2。默认情况下（没有重定向），每个进程的标准输入、标准输出和标准错误都指向控制终端，进程从标准输入读也就是读用户的键盘输入，进程往标准输出或标准错误输出写也就是输出到显示器上。在控制终端输入一些特殊的控制键可以给（前台）进程发送信号，如 &lt;code&gt;Ctrl+C&lt;/code&gt; 表示 SIGINT，&lt;code&gt;Ctrl+\&lt;/code&gt; 表示 SIGQUIT。&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ tty
/dev/pts/0
$ lsof /dev/pts/0
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
zsh     22773 huoty    0u   CHR  136,0      0t0    3 /dev/pts/0
zsh     22773 huoty    1u   CHR  136,0      0t0    3 /dev/pts/0
zsh     22773 huoty    2u   CHR  136,0      0t0    3 /dev/pts/0
zsh     22773 huoty   10u   CHR  136,0      0t0    3 /dev/pts/0
lsof    23297 huoty    0u   CHR  136,0      0t0    3 /dev/pts/0
lsof    23297 huoty    1u   CHR  136,0      0t0    3 /dev/pts/0
lsof    23297 huoty    2u   CHR  136,0      0t0    3 /dev/pts/0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;虚拟终端的数目是有限的，虚拟终端一般就是 /dev/tty1~/dev/tty6 六个。然而网络终端或图形终端窗口的数目却是不受限制的，这是通过 &lt;strong&gt;伪终端（Pseudo TTY）&lt;/strong&gt; 实现的。&lt;strong&gt;一套伪终端由一个主设备（PTY Master）和一个从设备（PTY Slave）组成&lt;/strong&gt;。主设备在概念上相当于键盘和显示器，只不过它不是真正的硬件而是一个内核模块，操作它的也不是用户而是另外一个进程。从设备和 /dev/tty1 这样的终端设备模块类似，只不过它的底层驱动程序不是访问硬件而是访问主设备。&lt;/p&gt;

&lt;p&gt;特殊设备 &lt;code&gt;/dev/ptmx&lt;/code&gt; 用于创建一对 master、slave 伪终端设备的文件。当一个进程打开它时，获得了一个 master 的文件描述符（file descriptor），同时在 /dev/pts 下创建了一个 slave 设备文件（如 /dev/pts/0, /dev/pts/1）。master 端是更接近用户显示器、键盘的一端，slave 端是在虚拟终端上运行的 CLI（Command Line Interface，命令行接口）程序。Linux 的伪终端驱动程序，会把 &lt;strong&gt;master端（如键盘）写入的数据&lt;/strong&gt; 转发给 slave 端供程序输入，把 &lt;strong&gt;程序写入 slave 端的数据&lt;/strong&gt; 转发给 master 端供（显示器驱动等）读取。如 ssh 远程登录的数据传输流程：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;+----------+       +------------+
| Keyboard |------&amp;gt;|            |
+----------+       |  Terminal  |
| Monitor  |&amp;lt;------|            |
+----------+       +------------+
                         |
                         |  ssh protocol
                         |
                         ↓
                   +------------+
                   |            |
                   | ssh server |--------------------------+
                   |            |           fork           |
                   +------------+                          |
                       |   ↑                               |
                       |   |                               |
                 write |   | read                          |
                       |   |                               |
                 +-----|---|-------------------+           |
                 |     |   |                   |           ↓
                 |     ↓   |      +-------+    |       +-------+
                 |   +--------+   | pts/0 |&amp;lt;----------&amp;gt;| shell |
                 |   |        |   +-------+    |       +-------+
                 |   |  ptmx  |&amp;lt;-&amp;gt;| pts/1 |&amp;lt;----------&amp;gt;| shell |
                 |   |        |   +-------+    |       +-------+
                 |   +--------+   | pts/2 |&amp;lt;----------&amp;gt;| shell |
                 |                +-------+    |       +-------+
                 |    Kernel                   |
                 +-----------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;关于终端和伪终端，可以简单的做如下理解：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;真正的硬件终端基本上已经看不到了，现在所说的终端、伪终端都是软件仿真终端(即终端模拟软件)&lt;/li&gt;
&lt;li&gt;一些连接了键盘和显示器的系统中，可以接触到运行在内核态的软件仿真终端(tty1-tty6)&lt;/li&gt;
&lt;li&gt;通过 GUI 的终端软件窗口或者 SSH 远程登录等使用的都是伪终端&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2bfd3a2ddcddee96&quot;&gt;作业控制&lt;/h2&gt;

&lt;p&gt;用户从终端登录系统时，大致会经历如下的过程：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;如果是字符界面登录，则由 init 进程调用 getty 来处理登录请求；如果是网络登录，如 ssh，则由 sshd 守护进程来处理登录请求&lt;/li&gt;
&lt;li&gt;getty/sshd 进程调用 &lt;code&gt;setsid&lt;/code&gt; 函数创建一个新的 &lt;strong&gt;Session&lt;/strong&gt;，该进程称为 &lt;strong&gt;Session Leader&lt;/strong&gt;，该进程的 pid 即为 Session 的 id&lt;/li&gt;
&lt;li&gt;getty 打开终端设备（如 /dev/tty1）作为控制终端；如果是非字符终端登录，则由相应的进程（如 sshd）打开一个伪终端设备，然后再 fork 一次，一分为二：父进程操作伪终端主设备，子进程将伪终端从设备作为控制终端。然后，进程都会将文件描述符 0、1、2 指向打开的控制终端。用了控制终端，进程就可以与用户交互了，接着就提示用户输入账户名&lt;/li&gt;
&lt;li&gt;输入账户后，进程通过调用 exec 变成 login 进程，然后提示输入密码，如果密码正确，则再调用 exec 变成 shell 进程。用户最终通过 shell 与操作系统交互&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shell 叫进程分为不同的 &lt;strong&gt;作业（Job）&lt;/strong&gt; 或者 &lt;strong&gt;进程组（Process Group）&lt;/strong&gt; 来进行控制，作业可以在 shell 的前台或者后台运行，这称为 &lt;strong&gt;作业控制（Job Control）&lt;/strong&gt;。一个前台作业可以由多个进程组成，一个后台作业也可以由多个进程组成，Shell可以同时运行一个前台作业和任意多个后台作业。如：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ proc1 | proc2 &amp;amp;
$ proc3 | proc4 | proc5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;其中 proc1 和 proc2 属于同一个后台进程组，proc3、proc4、proc5 属于同一个前台进程组，Shell 进程本身属于一个单独的进程组。这些进程组的控制终端相同，它们属于同一个 Session。&lt;strong&gt;Session（会话）可以看作是一个若干进程组的集合&lt;/strong&gt;。当用户在控制终端输入特殊的控制键（例如 Ctrl-C）时，内核会发送相应的信号（例如 SIGINT）给前台进程组的所有进程。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;amp;&lt;/code&gt; 表示将进程放到后台运行。另外，使用 jbos, bg, fg 等命令可以对作业进行查看和控制。&lt;/p&gt;

&lt;h2 id=&quot;part-2c5be0146b94d190&quot;&gt;守护进程&lt;/h2&gt;

&lt;p&gt;通过用户登录创建的进程，在运行结束或用户注销时终止。如通过终端登录创建的进程，在用户注销或网络中断时，通过终端 shell 启动的所有子进程都会受到 SIGHUP 信号，SIGHUP 信号的默认处理动作是退出进程。但系统中有一些服务进程不受用户登录注销的影响，它们一直在运行着，这样的进程被称为 &lt;strong&gt;守护进程（Daemon）&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;试着用 &lt;code&gt;ps axj&lt;/code&gt; 命令查看系统中的进程：（参数 a 表示不仅列当前用户的进程，也列出所有其他用户的进程，参数 x 表示不仅列有控制终端的进程，也列出所有无控制终端的进程，参数 j 表示列出与作业控制相关的信息）&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ ps axj
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    0     1     1     1 ?           -1 Ss       0   0:12 /sbin/init splash
    0     2     0     0 ?           -1 S        0   0:00 [kthreadd]
    2     3     0     0 ?           -1 I&amp;lt;       0   0:00 [rcu_gp]
    2     4     0     0 ?           -1 I&amp;lt;       0   0:00 [rcu_par_gp]
    2     6     0     0 ?           -1 I&amp;lt;       0   0:00 [kworker/0:0H-events_highpri]
    2     9     0     0 ?           -1 I&amp;lt;       0   0:00 [mm_percpu_wq]
    2    10     0     0 ?           -1 S        0   0:02 [ksoftirqd/0]
...
22771 22773 22773 22773 pts/0    28246 Ss    1000   0:03 -zsh
...
22773 28246 28246 22773 pts/0    28246 R+    1000   0:00 ps axj
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;TPGID 为 -1 的进程都是没有控制终端的进程，也就是守护进程（TPGID 指前台进程组 ID）。在 COMMAND 一列用 &lt;strong&gt;[]&lt;/strong&gt; 括起来的名字表示内核线程，这些线程在内核里创建，没有用户空间代码，因此没有程序文件名和命令行，通常采用以 k 开头的名字，表示 Kernel。init 进程第一个用户级进程，其有许多很重要的任务，如启动 getty（用于用户登录）；udevd负责维护 /dev 目录下的设备文件；acpid 负责电源管理；syslogd 负责维护 /var/log 下的日志文件。可以看出，守护进程通常采用以 d 结尾的名字，表示 Daemon。&lt;/p&gt;

&lt;p&gt;SIGHUP 信号在用户终端连接（正常或非正常）结束时发出, 通常是在终端的控制进程结束时, 通知同一 Session 内的各个作业。系统对 SIGHUP 信号的默认处理是终止收到该信号的进程。所以要创建一个守护进程，就需要脱离原来的 Session，并且不能有控制终端。&lt;/p&gt;

&lt;p&gt;创建守护进程最关键的一步是调用 setsid 函数创建一个新的 Session，并成为 Session Leader。&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;unistd.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pid_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setsid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;该函数调用成功时返回新创建的 Session 的 id（其实也就是当前进程的 id），出错返回 -1。注意，调用这个函数之前，当前进程不允许是进程组的 Leader，否则该函数返回 -1。要保证当前进程不是进程组的 Leader 也很容易，只要先 fork 再调用 setsid 就行了。fork 创建的子进程和父进程在同一个进程组中，进程组的 Leader 必然是该组的第一个进程，所以子进程不可能是该组的第一个进程，在子进程中调用 setsid 就不会有问题了。&lt;/p&gt;

&lt;p&gt;成功调用 setsid 函数的结果是：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;创建一个新的 Session，当前进程成为 Session Leader，当前进程的 id 就是 Session 的 id&lt;/li&gt;
&lt;li&gt;创建一个新的进程组，当前进程成为进程组的 Leader，当前进程的 id 就是进程组的 id&lt;/li&gt;
&lt;li&gt;如果当前进程原本有一个控制终端，则它失去这个控制终端，成为一个没有控制终端的进程。所谓失去控制终端是指，原来的控制终端仍然是打开的，仍然可以读写，但只是一个普通的打开文件而不是控制终端了&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;示例：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;fcntl.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;daemonize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pid_t&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/*
     * Become a session leader to lose controlling TTY.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fork&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* parent */&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;setsid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/*
     * Change the current working directory to the root.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;chdir&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/*
     * Attach file descriptors 0, 1, and 2 to /dev/null.
     */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/dev/null&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;O_RDWR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dup2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dup2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;daemonize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;part-2bb23717ee7e9bfc&quot;&gt;参考资料&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://segmentfault.com/a/1190000016129862&quot;&gt;https://segmentfault.com/a/1190000016129862&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://segmentfault.com/a/1190000009082089&quot;&gt;https://segmentfault.com/a/1190000009082089&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://akaedu.github.io/book/ch34s03.html&quot;&gt;https://akaedu.github.io/book/ch34s03.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://akaedu.github.io/book/ch34s02.html&quot;&gt;https://akaedu.github.io/book/ch34s02.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://akaedu.github.io/book/ch34s03.html&quot;&gt;https://akaedu.github.io/book/ch34s03.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cnblogs.com/zzdyyy/p/7538077.html&quot;&gt;https://www.cnblogs.com/zzdyyy/p/7538077.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Thu, 02 Apr 2020 00:00:00 +0800</pubDate>
        <link>https://donothing.site/2020/04/02/terminal-jobs-daemon/</link>
        <guid isPermaLink="true">https://donothing.site/2020/04/02/terminal-jobs-daemon/</guid>
        
        <category>linux</category>
        
        
        <category>Linux</category>
        
      </item>
    
      <item>
        <title>网址收藏</title>
        <description>&lt;p&gt;“好记性不如烂笔头”，收录常用网址，有用的工具、资料网站，以及其他一些感兴趣的网站。&lt;/p&gt;

&lt;h2 id=&quot;part-2c9a358243a7f1b4&quot;&gt;常用网址&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zhihu.com/&quot;&gt;知乎&lt;/a&gt;: 知乎问答平台&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://mail.163.com/&quot;&gt;163邮箱&lt;/a&gt;: 163邮箱&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://mail.qq.com/&quot;&gt;QQ邮箱&lt;/a&gt;: QQ邮箱&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.12306.cn/&quot;&gt;12306&lt;/a&gt;: 中国铁路火车票网上预定平台&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.aliyun.com/&quot;&gt;阿里云&lt;/a&gt;: 阿里云服务平台&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://zhanzhang.baidu.com/dashboard/index&quot;&gt;百度站长平台&lt;/a&gt;: 百度站长平台&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tongji.baidu.com/&quot;&gt;百度统计&lt;/a&gt;: 百度统计&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jd.com/&quot;&gt;京东&lt;/a&gt;: 京东网上购物&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.taobao.com/&quot;&gt;淘宝&lt;/a&gt;: 淘宝网，淘你喜欢&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.tmall.com/&quot;&gt;天猫&lt;/a&gt;: 理想生活上天猫&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zhaopin.com/&quot;&gt;智联招聘&lt;/a&gt;: 智联招聘&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zol.com.cn/&quot;&gt;中关村在线&lt;/a&gt;: 中关村在线&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.lagou.com/&quot;&gt;拉勾网&lt;/a&gt;: 拉勾网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://signin.aliyun.com&quot;&gt;阿里云RAM&lt;/a&gt;: 阿里云 RAM 用户登录&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2b840e24f2af930b&quot;&gt;兴趣爱好&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.gushiwen.org/&quot;&gt;古诗文网&lt;/a&gt;: 古诗文网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.shicimingju.com&quot;&gt;诗词名句网&lt;/a&gt;: 诗词名句网 - 古诗词大全|诗歌|诗词鉴赏|古诗名句|诗句赏析！&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.hx5q.cn/&quot;&gt;古文诗词鉴赏&lt;/a&gt;: 古文诗词鉴赏&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ctext.org/zhs&quot;&gt;Chinese Text&lt;/a&gt;: 中国哲学书电子化计划&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://lib.xcz.im/&quot;&gt;西窗烛&lt;/a&gt;: 中华诗词数据库&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.polayoutu.com/collections&quot;&gt;泼辣有图&lt;/a&gt; 开源摄影，为世界提供免费美丽图像&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tuchong.com/&quot;&gt;图虫网&lt;/a&gt;: 图虫网 - 最好的摄影师都在这儿&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://1x.com/&quot;&gt;1x&lt;/a&gt;: 1x - Curated photography&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://500px.com/&quot;&gt;500px&lt;/a&gt;: 最出色的摄影社区 / 500px&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://7mx.com/&quot;&gt;7MX&lt;/a&gt;: 视觉创作社区&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bbs.fengniao.com/&quot;&gt;蜂鸟摄影&lt;/a&gt;: 蜂鸟摄影论坛&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.pop-photo.com.cn/&quot;&gt;大众摄影&lt;/a&gt;: 大众摄影网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://unsplash.com/&quot;&gt;Unsplash&lt;/a&gt;: Beautiful Free Images&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.picperweek.com/&quot;&gt;美图每周&lt;/a&gt;: 美图每周&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pixabay.com/&quot;&gt;Pixabay&lt;/a&gt;: 免费图片搜索&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lssdjt.com/&quot;&gt;历史上的今天&lt;/a&gt;: 让历史照亮显示，让今天看清方向&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.allhistory.com/&quot;&gt;全历史&lt;/a&gt;: 比较全面的历史知识讲解&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.chinadaily.com.cn/&quot;&gt;中国日报&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://news.cctv.com/&quot;&gt;央视新闻&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.thepaper.cn/&quot;&gt;澎湃新闻&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.msn.com/zh-tw/news&quot;&gt;台湾即时新闻&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.bbc.com/&quot;&gt;BBC &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2bff38ab69576357&quot;&gt;在线翻译&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://fanyi.baidu.com&quot;&gt;百度翻译&lt;/a&gt;: 百度翻译&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://translate.google.cn/&quot;&gt;Google翻译&lt;/a&gt;: Google翻译&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.iciba.com/&quot;&gt;iCIBA爱词霸&lt;/a&gt;: iCIBA爱词霸&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://fanyi.youdao.com/&quot;&gt;有道翻译&lt;/a&gt;: 有道翻译&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.bing.com/translator/&quot;&gt;必应Translator&lt;/a&gt;: 必应Translator&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2edf970f78a939e6&quot;&gt;音乐放松&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.yinyuetai.com/&quot;&gt;音乐Tai&lt;/a&gt;: 音乐Tai&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.xiami.com/&quot;&gt;虾米音乐&lt;/a&gt;: 虾米音乐&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://y.qq.com/&quot;&gt;QQ音乐&lt;/a&gt;: QQ音乐&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://music.163.com/&quot;&gt;网易云音乐&lt;/a&gt;: 网易云音乐&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.kugou.com/&quot;&gt;酷狗音乐&lt;/a&gt;: 酷狗音乐&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://5sing.kugou.com/&quot;&gt;5sing&lt;/a&gt;: 5sing中国原创音乐基地&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://lebo.baidu.com/&quot;&gt;百度乐播&lt;/a&gt;: 百度乐播&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://music.migu.cn/&quot;&gt;咪咕音乐&lt;/a&gt;: 咪咕音乐&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.calm.com/&quot;&gt;Calm.com&lt;/a&gt;: Calm&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.getrelaxed.com/&quot;&gt;GetRelaxed.com&lt;/a&gt;: Reduce Your Stress&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.donothingfor2minutes.com/&quot;&gt;Do Nothing for 2 Minutes&lt;/a&gt;: Do Nothing for 2 Minutes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.loungev.com/&quot;&gt;LoungeV Studio&lt;/a&gt;: Relaxing Nature Videos : Full HD and 4K UHD Films&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://asoftmurmur.com/&quot;&gt;A Soft Murmur&lt;/a&gt;: A Soft Murmur&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2d3cf2ce7b84ebd9&quot;&gt;电影视频&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.youku.com/&quot;&gt;优酷&lt;/a&gt;: 这世界有点酷&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mp4ba.la/&quot;&gt;MP4吧&lt;/a&gt;: 高清MP4吧&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rrys2019.com/&quot;&gt;YYeTs&lt;/a&gt;: 人人字幕组&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ddrk.me/&quot;&gt;低端影视&lt;/a&gt;: 超清在线视频站&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.biyov.com/&quot;&gt;比优视频&lt;/a&gt;: 人生如戏&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.novipnoad.com/&quot;&gt;NO视频&lt;/a&gt;: 不负追剧好时光&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.doki8.com/&quot;&gt;doki8&lt;/a&gt;: 心动日剧&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zzrbl.com/&quot;&gt;猪猪日部落&lt;/a&gt;: 猪猪日剧字幕组&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bde4.com/&quot;&gt;哔嘀影视&lt;/a&gt;: 热门最新电影&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://1090ys.com/&quot;&gt;1090影视&lt;/a&gt;: 挺全的电影&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.shenma4480.com/&quot;&gt;神马影院&lt;/a&gt;: 神马都有？&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ttdytt.cc/&quot;&gt;天天电影天堂&lt;/a&gt;: 电影下载，请认准T天T天D电Y影T天T堂网址&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2c919f6a3514f23d&quot;&gt;工具资料&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://wyw.hwxnet.com&quot;&gt;汉语言文学网&lt;/a&gt;: 文言文字典|古汉语字典|文言文翻译|文言文大全-汉语言文学网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gw.eywedu.com&quot;&gt;文言文在线词典&lt;/a&gt;: 文言文在线词典&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.fantizi5.com&quot;&gt;繁体字网&lt;/a&gt;: 繁体字网-繁体字查询-繁体字在线转换-繁体字转换器&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.processon.com/&quot;&gt;ProcessOn&lt;/a&gt;: 在线流程图绘制工具&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.uupoop.com/&quot;&gt;PS 在线版&lt;/a&gt;: Photoshop 在线精简版&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://xiuxiu.web.meitu.com/&quot;&gt;美图秀秀网页版&lt;/a&gt;: 美图秀秀网页版&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.easyicon.net/&quot;&gt;Easyicon.net&lt;/a&gt;: easyicon.net&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.uugai.com/&quot;&gt;U钙网免费Logo设计&lt;/a&gt;:  U钙网，免费 logo 设计&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jiqie.com/h/&quot;&gt;免费印章在线制作&lt;/a&gt;: 免费印章在线制作&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tinypng.com/&quot;&gt;TinyPNG&lt;/a&gt;: 在线图片压缩工具&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docsmall.com&quot;&gt;docsmall&lt;/a&gt;: 在线图片压缩、PDF压缩工具&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.docker.org.cn/&quot;&gt;OSChina在线工具&lt;/a&gt;: 在线工具--OSChina&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://tool.lu/&quot;&gt;在线工具--做最专业的工具网站&lt;/a&gt;: 在线工具--做最专业的工具网站&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://maxiang.io/&quot;&gt;马克飞象&lt;/a&gt;: 马克飞象&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://markdown.xiaoshujiang.com/&quot;&gt;小书匠&lt;/a&gt;: 小书匠&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.dzzoffice.com/&quot;&gt;DzzOffice&lt;/a&gt;: 大桌子云办公平台&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pythontutor.com/&quot;&gt;Pythontutor.com&lt;/a&gt;: Online Python Tutor&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ideone.com/&quot;&gt;Ideone.com&lt;/a&gt;: Ideone.com&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://codepad.org/&quot;&gt;Codepad.org&lt;/a&gt;: Codepad.org&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://hao.uisdc.com/&quot;&gt;设计师网址导航&lt;/a&gt;: 设计师网址导航&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zybuluo.com/cmd/&quot;&gt;Cmd Markdown&lt;/a&gt;: Cmd 在线 Markdown 编译器&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.tool.la/css20/&quot;&gt;CSS样式中文手册&lt;/a&gt;: CSS样式中文手册&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.tool.la/&quot;&gt;TOOL工具啦&lt;/a&gt;: TOOL工具啦&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.debian.org/doc/manuals/maint-guide/index.zh-cn.html&quot;&gt;Debian 新维护人员手册&lt;/a&gt;: Debian 新维护人员手册&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://git-scm.com/book/zh/v2&quot;&gt;Git-Book 简体中文&lt;/a&gt;: Git-Book 简体中文&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.kuqin.com/abyteofpython_cn/index.html&quot;&gt;简明 Python 教程&lt;/a&gt;: 简明 Python 教程&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.shoucewang.com/&quot;&gt;手册网&lt;/a&gt;: 手册网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.chinaunix.net/uid-26275986-id-4070559.html&quot;&gt;操作系统安全&lt;/a&gt;: 操作系统安全--技术博客&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://programgo.com/&quot;&gt;博客文章收藏网&lt;/a&gt;: 博客文章收藏网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://awk.js.org/&quot;&gt;AWK 在线测试工具&lt;/a&gt;: 提供 awk 在线交互式解释器&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.iconfont.cn/&quot;&gt;IconFont&lt;/a&gt;: 阿里巴巴图标库&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2ca6bdb5d5474ed0&quot;&gt;开源世界&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.github.com&quot;&gt;GitHub.com&lt;/a&gt;: GitHub官方网站&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://git.oschina.net/&quot;&gt;Git@OSC&lt;/a&gt;: Git@OSC&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.oschina.net/&quot;&gt;开源中国&lt;/a&gt;: 开源中国&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://imcn.me/&quot;&gt;IMCN&lt;/a&gt;: IMCN&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://coding.net/&quot;&gt;Coding&lt;/a&gt;: Coding&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bitbucket.org/&quot;&gt;Bitbucket&lt;/a&gt;: The Git solution for professional teams&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sourceforge.net&quot;&gt;SourceForge.net&lt;/a&gt;: SourceForge.net&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com&quot;&gt;GoogleCode.com&lt;/a&gt;: GoogleCode.com&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.chinaunix.net/&quot;&gt;ChinaUnix&lt;/a&gt;: ChinaUnix&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.linuxeden.com/&quot;&gt;Linux伊甸园&lt;/a&gt;: Linux伊甸园&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.linuxstory.org/&quot;&gt;LinuxStory&lt;/a&gt;: LinuxStory&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.ubuntuthemes.org/&quot;&gt;Ubuntuthemes&lt;/a&gt;: Ubuntuthemes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gnome-look.org/&quot;&gt;GNOME-LOOK.ORG&lt;/a&gt;: gnome-look&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.omgubuntu.co.uk/&quot;&gt;OMGUbuntu&lt;/a&gt;: omgubuntu&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2c4a3c36a26123fa&quot;&gt;技术社区&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.w3cschool.cn/&quot;&gt;W3cschool.cn&lt;/a&gt;: W3cschool.cn&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.w3cschool.cc/&quot;&gt;菜鸟教程&lt;/a&gt;: 菜鸟教程&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.w3school.com.cn/&quot;&gt;W3school&lt;/a&gt;: W3school&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jobbole.com/&quot;&gt;伯乐在线&lt;/a&gt;: JOBBOLE伯乐在线&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://toutiao.io/&quot;&gt;开发者头条&lt;/a&gt;: 开发者头条 - 程序员的首选学习分享平台&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.joinquant.com/community&quot;&gt;社区 - JoinQuant&lt;/a&gt;: 社区 - JoinQuant&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.yiibai.com/&quot;&gt;易百教程&lt;/a&gt;: 易百教程&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.codeceo.com/&quot;&gt;码农网&lt;/a&gt;: 码农网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://c.biancheng.net/&quot;&gt;Ｃ语言中文网&lt;/a&gt;: Ｃ语言中文网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.simplexue.com/&quot;&gt;西晋学院&lt;/a&gt;: 西晋学院&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.imooc.com/&quot;&gt;慕课网&lt;/a&gt;: 慕课网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jikexueyuan.com/&quot;&gt;极课学院&lt;/a&gt;: 极课学院&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sqlite.org/&quot;&gt;SQLite官方网站&lt;/a&gt;: SQLite官方网站&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.1keydata.com/cn/sql/&quot;&gt;SQL语句教程&lt;/a&gt;: SQL语句教程--1keydata&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.php100.com/&quot;&gt;PHP100&lt;/a&gt;: PHP100&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.phpchina.com/&quot;&gt;PHPChina&lt;/a&gt;: PHP 技术交流论坛&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.w3cfuns.com&quot;&gt;W3Cfuns&lt;/a&gt;: W3Cfuns&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.1keydata.com/&quot;&gt;1keydata&lt;/a&gt;: 1Keydata - Free Online Programming Tutorial&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.icoolxue.com/&quot;&gt;爱酷学习网&lt;/a&gt;: 爱酷学习网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.kuqin.com/&quot;&gt;酷勤网&lt;/a&gt;: 酷勤网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.51zxw.net/&quot;&gt;我要自学网&lt;/a&gt;: 我要自学网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.51xue8.com/&quot;&gt;51学吧&lt;/a&gt;: 51学吧&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.shiyanlou.com/&quot;&gt;实验楼&lt;/a&gt;: 实验楼&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ruby-china.org/&quot;&gt;RubyChina社区&lt;/a&gt;: RubyChina社区&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.ruby-lang.org&quot;&gt;Ruby-lang.org&lt;/a&gt;: Ruby-lang.org&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://wiki.woodpecker.org.cn/&quot;&gt;啄木鸟社区&lt;/a&gt;: Woodpecker Wiki for CPUG&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.v2ex.com/&quot;&gt;V2EX&lt;/a&gt;: V2EX 是一个关于分享和探索的地方&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.simple-is-better.com/&quot;&gt;Python4cn&lt;/a&gt;:  Python4cn:文章 招聘 软件 酷站&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.liaoxuefeng.com/&quot;&gt;廖雪峰的官方网站&lt;/a&gt;: 廖雪峰的官方网站&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.pythontab.com/&quot;&gt;PythonTab&lt;/a&gt;: PYTHON开发者门户&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.iplaypython.com/&quot;&gt;玩蛇网&lt;/a&gt;: 玩蛇网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cnpythoner.com/&quot;&gt;老王Python&lt;/a&gt;: 老王Python提供简单实用的Python教程&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.pythondoc.com/&quot;&gt;Python 中文学习大本营&lt;/a&gt;: Python 中文学习大本营&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://python.freelycode.com/&quot;&gt;Python 部落&lt;/a&gt;: Python 部落&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.ziqiangxuetang.com/django/django-tutorial.html&quot;&gt;Django基础教程&lt;/a&gt;: Django基础教程&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.lhelper.org/dev/django_step_by_step/newtest/doc/&quot;&gt;Django Step by Step&lt;/a&gt;: Django Step by Step&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.python88.com/&quot;&gt;Python中国社区&lt;/a&gt;: Python中国社区 - 专注于Python中国技术发展的社区&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://flask123.sinaapp.com/&quot;&gt;Flask 中文学习网&lt;/a&gt;: 分享Flask教程、扩展插件、编程技巧&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.codingpy.com/&quot;&gt;编程派&lt;/a&gt;: 编程派(codingpy)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.docker.org.cn/&quot;&gt;Docker 中文社区&lt;/a&gt;: Docker 中文社区&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2e9bff25d49c8225&quot;&gt;资源搜索&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://pkgs.org/&quot;&gt;Pkgs.org&lt;/a&gt;: Linux 软件包搜索平台&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://rpm.pbone.net/&quot;&gt;RPM Search&lt;/a&gt;: RPM 软件包搜索&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://nullege.com/&quot;&gt;Nullege.com&lt;/a&gt;: Python 源码搜索引擎&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.lfd.uci.edu/&quot;&gt;LFD&lt;/a&gt;: LFD&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.programcreek.com/&quot;&gt;Programcreek.com&lt;/a&gt;: Programcreek.com&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2e161d25fdd8f4e1&quot;&gt;网络云盘&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://yun.baidu.com/&quot;&gt;百度云&lt;/a&gt;: 百度云&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://yunpan.360.cn/&quot;&gt;360云盘&lt;/a&gt;: 360云盘&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kanbox.com/&quot;&gt;酷盘&lt;/a&gt;: 酷盘&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.weiyun.com/&quot;&gt;微云&lt;/a&gt;: 腾讯微云&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.qiniu.com/&quot;&gt;七牛云存储&lt;/a&gt;: 七牛云存储&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cowtransfer.com/&quot;&gt;奶牛快传&lt;/a&gt;: 安全、省时高效&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.wenshushu.cn/&quot;&gt;文叔叔&lt;/a&gt;: 传文件的酸爽！&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://send.firefox.com/&quot;&gt;FirefoxSend&lt;/a&gt;: 安全高效火狐传送&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://app.tmp.link/&quot;&gt;TMPLink&lt;/a&gt;: 简单临时文件中转&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2c6f8217e29a17b1&quot;&gt;搜索引擎&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.baidu.com/&quot;&gt;百度搜索&lt;/a&gt;: 百度搜索&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/ncr&quot;&gt;Google.com&lt;/a&gt;: 谷歌搜索&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.bing.com/?FORM=HPCNEN&quot;&gt;Bing.com&lt;/a&gt;: 必应搜索&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://duckduckgo.com/&quot;&gt;DuckDuckGo&lt;/a&gt;: DuckDuckGo&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.haosou.com/&quot;&gt;360好搜&lt;/a&gt;: 360好搜&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sogou.com/&quot;&gt;搜狗搜索&lt;/a&gt;: 搜狗搜索&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sg.search.yahoo.com/&quot;&gt;YAHOO中国雅虎&lt;/a&gt;: YAHOO 中国雅虎&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.ask.com&quot;&gt;Ask.com&lt;/a&gt;: Ask.com&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.webcrawler.com&quot;&gt;Webcrawler.com&lt;/a&gt;: Webcrawler.com&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.lycos.com/&quot;&gt;Lycos.com&lt;/a&gt;: Lycos.com&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2b845da0e2df84cd&quot;&gt;其他链接&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.joinquant.com/&quot;&gt;JoinQuant&lt;/a&gt;: 聚宽量化交易平台&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://yonsm.net/&quot;&gt;Yonsm.NET&lt;/a&gt;: Yonsm.NET&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://jeffjade.com/&quot;&gt;晚晴幽草轩&lt;/a&gt;: 晚晴幽草轩&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cnseay.com/&quot;&gt;Seay博客&lt;/a&gt;: Seay博客 渗透 编程 创业 代码安全审计 致力于更专业的网络安全博客&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://funhacks.net/&quot;&gt;FunHacks&lt;/a&gt;: Have fun hacking&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://foofish.net/&quot;&gt;Python之禅&lt;/a&gt;: Python之禅 - FooFish&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://github.thinkingbar.com/&quot;&gt;飘过的小牛&lt;/a&gt;: 飘过的小牛&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.yinwang.org/&quot;&gt;王垠的博客&lt;/a&gt;: 王垠的博客&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.simapple.com/&quot;&gt;简果网&lt;/a&gt;: 简果网-专注IT技术和互联网&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.crifan.com/&quot;&gt;在路上&lt;/a&gt;: 在路上&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.webhek.com/&quot;&gt;WEB骇客&lt;/a&gt;: WEB骇客&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.qaulau.com/&quot;&gt;侠客创想&lt;/a&gt;: 记录成长的点滴,分享互联网的那些事&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://coolshell.cn/&quot;&gt;酷 壳&lt;/a&gt;: 酷壳 – CoolShell.cn&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.iswtf.com/&quot;&gt;isWTF&amp;#39;s blog&lt;/a&gt;: isWTF&amp;#39;s blog&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.wklken.me/&quot;&gt;wklken&amp;#39;s blog&lt;/a&gt;: wklken&amp;#39;s blog&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pyzh.readthedocs.io/&quot;&gt;PyZh&lt;/a&gt;: PyZh -- 一起写Python文章，一起看Python文章&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jianshu.com/users/5qrPPM/latest_articles&quot;&gt;人世间&lt;/a&gt;: 人世间-简书&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 28 Mar 2020 00:00:00 +0800</pubDate>
        <link>https://donothing.site/urlbook/</link>
        <guid isPermaLink="true">https://donothing.site/urlbook/</guid>
        
        <category>vim</category>
        
        
        <category>文本编辑</category>
        
      </item>
    
      <item>
        <title>Vim 使用技巧整理</title>
        <description>&lt;p&gt;Vim 是 VIMproved 的缩写，即 Vim 编辑器是 Vi 编辑器的改进版。Vim 采用模式编辑的理念，其提供多种操作模式，按键在不同的模式下作用不同。 如，普通模式用于浏览文件，插入模式用于插入文本，可视模式下可以选择行或文本块，命令模式可以执行命令等等。&lt;/p&gt;

&lt;p&gt;和模式编辑紧密相连的概念是 &lt;code&gt;操作符&lt;/code&gt; 和 &lt;code&gt;动作&lt;/code&gt;。&lt;strong&gt;操作符&lt;/strong&gt; 指的是开始某个行为，如修改、删除或者选择文本；之后你要用一个 &lt;strong&gt;动作&lt;/strong&gt; 来指定需要操作的文本区域。比如，要改变括号内的文本，需要执行 &lt;code&gt;ci(&lt;/code&gt;（读做 change inner parentheses）；删除整个段落的内容，需要执行 &lt;code&gt;dap&lt;/code&gt;（读做：delete around paragraph）。&lt;/p&gt;

&lt;p&gt;Vim 存在一个兼容模式，该模式让 Vim 兼容 Vi。在兼容模式下运行时，Vim 大部分增强及改善的功能将不可用。需注意的是，这种模式下，Vim 并不能简单等同 Vi - 此模式只是设定一些类似 Vi 编辑器工作方式的默认选项。&lt;/p&gt;

&lt;p&gt;Vim 包含三种不同的操作模式，即 &lt;strong&gt;命令模式&lt;/strong&gt;（或者叫 &lt;strong&gt;普通模式&lt;/strong&gt;）、&lt;strong&gt;插入模式&lt;/strong&gt;、&lt;strong&gt;底行命令模式&lt;/strong&gt;。使用 &lt;code&gt;ESC&lt;/code&gt;，&lt;code&gt;i&lt;/code&gt;/&lt;code&gt;o&lt;/code&gt;/&lt;code&gt;a&lt;/code&gt;等，&lt;code&gt;:&lt;/code&gt; 来切换不同模式。打开 Vim 时，默认停留在 命令模式，按 i 等键可以进入 插入模式 进行文本编辑，按 ESC 键可以退出编辑模式，然后输入 : 可进入底行命令模式。编辑模式和底行命令模式都只能从命令模式进入，ESC 键主要用于退出编辑模式和底行命令模式。另外，还有两种常用的工作模式，&lt;strong&gt;可视模式 (Visual-mode)&lt;/strong&gt; 与 &lt;strong&gt;粘贴模式（Paste-mode）&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;在以下的描述中，所有以 &lt;code&gt;:&lt;/code&gt; 开头的命令都表示在底行命令模式下的命令，所有不以 : 开头的命令都表示在普通模式下的命令。&lt;/p&gt;

&lt;p&gt;Vim 自带一个交互式的教程，包含一些基础的操作，可以通过终端运行以下命令打开教程来练习使用：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ vimtutor
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;part-65429b37f4b&quot;&gt;基础&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;打开文件&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;从命令行中打开：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;打开文件
$ vim filename

当指定一个目录时会打开一个目录树
$ vim dirname

打开多个文件并横向分屏
$ vim -o file1 file2 file3

打开多个文件并纵向分屏
$ vim -o file1 file2 file3

打开文件并调到指定行
$ vim filename +num

在打开文件前，先执行指定的命令
vim -c cmd filename

恢复上次异常退出的文件
vim -r filename

以只读的方式打开文件，但可以强制保存
vim -R filename

只读的方式打开文件，不可以强制保存
vim -M filename

打开文件，并将光标停留在第一个找到的 string 上
vim +/string filename

用已有的 vim 进程打开指定的文件
vim --remote filename
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;从 Vim 中打开文件：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;打开文件
:e filename

打开目录树（默认打开当前目录）
:Ex dirname

打开一个文件并横向分屏
:sp filename
:split filename

打开一个文件并纵向分屏
:vsp filename
:vsplit filename

打开以光标所在字符串为文件名的文件
gf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;保存与退出&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:w -- 保存修改
:wa[ll] -- 保存所有修改过的窗口
:wq -- 保存并退出
:x -- 保存并退出
ZZ -- 保存并退出

:n1,n2w filename -- 选择性保存从某n1行到另n2行的内容

:saveas newfilename -- 另存为

:q[uit]  -- 退出 vim
:q! -- 强制退出（放弃修改）
:qa[ll] -- 关闭所有窗口，退出vim

:close -- 关闭当前窗口

:only -- 只保留当前窗口，关闭其它窗口(CTRL-W o)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;缓冲区&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;缓冲区是一个文件的内容占用的那部分 Vim 内存。每一份文件都是在他们自己独有的缓冲区打开的，每次文本都是作为缓冲区的一部分显示的。列出缓冲区可以用如下三个命令：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:buffers
:files
:ls
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:ls
  1 %a   &quot;test1&quot;                        line 1
  2      &quot;test2&quot;                        line 0
  3      &quot;test3&quot;                        line 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;其中，第一列是文件编号，第二列是缓冲文件的状态，第三列是文件的名称，第四列是上一次编辑的位置。 缓冲文件的状态有如下几种（仅供参考）：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-&lt;/code&gt; 非活动的缓冲区&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a&lt;/code&gt; 当前被激活缓冲区（光标所在的缓冲区）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;h&lt;/code&gt; 隐藏的缓冲区&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%&lt;/code&gt; 当前的缓冲区（指当前窗口可见的缓冲区，因为可以分割窗口，可能有多个）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#&lt;/code&gt; 交换缓冲区&lt;/li&gt;
&lt;li&gt;&lt;code&gt;=&lt;/code&gt; 只读缓冲区&lt;/li&gt;
&lt;li&gt;&lt;code&gt;+&lt;/code&gt; 已经更改的缓冲区&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;切换工作区用 &lt;code&gt;:buffer&lt;/code&gt;/&lt;code&gt;:b&lt;/code&gt; 命令，或者用 &lt;code&gt;:sbuffer&lt;/code&gt;/&lt;code&gt;sb&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:[s]b 编号
:[s]buffer 文件名

:[s]bn[ext]
:[s]bp[revious]
:[s]bl[ast]
:[s]bf[irst]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;添加或删除缓冲区&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;添加一个文件到缓存区
:bad[d] 文件名

新建一个未命名的缓冲区
:enew

从缓冲区删除一个文件
:bdel[ete] 文件名/编号
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;参数列表&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;缓冲区列表是 Vim 的特性。在这之前的 vi 中，仅仅只有参数列表，参数列表在 Vim 中依旧可以使用。&lt;/p&gt;

&lt;p&gt;每一个通过 shell 命令传递给 Vim 的文件名都被记录在一个参数列表中。可以有多个参数列表：默认情况下所有参数都被放在全局参数列表下，但是你可以使用 &lt;code&gt;:arglocal&lt;/code&gt; 命令去创建一个新的本地窗口的参数列表。&lt;/p&gt;

&lt;p&gt;使用 &lt;code&gt;:args&lt;/code&gt; 命令可以列出当前参数。使用 &lt;code&gt;:next&lt;/code&gt;，&lt;code&gt;:previous&lt;/code&gt;，&lt;code&gt;:first&lt;/code&gt;，&lt;code&gt;:last&lt;/code&gt; 命令可以切换在参数列表中的文件。通过使用 &lt;code&gt;:argadd&lt;/code&gt;，&lt;code&gt;:argdelete&lt;/code&gt; 或者 &lt;code&gt;:args&lt;/code&gt; 等命令改变参数列表。&lt;/p&gt;

&lt;p&gt;参数列表在有些情况下是非常有用的，如使用 &lt;code&gt;:argdo&lt;/code&gt; 做批处理，示例：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:args **/*.[ch]
:argdo %s/foo/bar/ge | update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;以上命令将替换掉当前目录以及其子目录中所有的 C 源文件和头文件中的 “foo” 为 “bar”。&lt;code&gt;:argdo&lt;/code&gt; 命令会对参数列表中的文件执行相同的动作。&lt;/p&gt;

&lt;p&gt;更多关于参数列表的信息，可以通过查阅离线文档了解 &lt;code&gt;:h argument-list&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;标签/窗口&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;窗口 是缓冲区更上一层的视窗。如果想同时查看几个文件或者查看同一文件的不同位置，则可以开启多个窗口。窗口可以水平或者竖直分割并且现有窗口的高度和宽度可以被调节。&lt;/p&gt;

&lt;p&gt;打开多个窗口可以用以下命令：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;# 横向打开一个新窗口
:sp[lit]
:sp[lit] filename
:new
:new filename

# 纵向打开一个新窗口
:vsp[lit]
:vsp[lit] filename

ctrl-w s  上下分割当前文件
ctrl-w v  左右分割当前文件

# 水平分割一个窗口，浏览文件系统
:Sex

# 垂直分割一个窗口，浏览文件系统
:Vex
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;窗口大小纵向调整:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:ctrl+w +  纵向扩大（行数增加）
:ctrl+w -  纵向缩小 （行数减少）
:res(ize) num  如 :res 5，显示行数调整为5行
:res(ize) +num  把当前窗口高度增加 num 行
:res(ize) -num  把当前窗口高度减少 num 行
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;窗口大小横向调整:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:vertical res(ize) num  指定当前窗口为num列
:vertical res(ize)+num  把当前窗口增加num列
:vertical res(ize)-num  把当前窗口减少num列
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;标签页 是可以容纳一系列 窗口 的容器。打开标签可以使用以下命令&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:tabe[dit] [文件名]
:tabnew [文件名]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;切换标签页：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;# 下一个标签
gt
:tabn[ext]

# 上一个标签页
gT
:tabp[revious]

# 快速切换到第一个标签或最后一个标签
:tabfir[st]  :tabr[ewind]
:tabl[ast]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;使用 &lt;code&gt;:e&lt;/code&gt; 或 &lt;code&gt;ctrl+^&lt;/code&gt; 可以回到刚才编辑的文件，这已操作感觉很实用。&lt;/p&gt;

&lt;p&gt;其他操作：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;# 显示所有标签
:tabs

# 关闭标签
:tabc[lose]

# 关闭所有其他标签页，只保留当前活动标签页
:tabo[nly]

# 将当前标签页移到第 n 个标签页之后
:tabm[ove] N

# 同时在多个标签页中执行命令
:tabdo command

如 :tabdo %s/food/drink/g 可一次完成对所有文件的替换操作，而不用针对每个文件重复操作
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;随便说一下，缓冲区列表是全局可见的，可以在任何标签中访问任何一个缓冲区。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;寄存器&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;寄存器是存储文本内容的空间。常用的「复制」操作就是把文本存储到寄存器，「粘贴」操作就是把文本从寄存器中读出来。例如常用的复制快捷键 y，粘贴快捷键 p，也都是对寄存器（匿名寄存器 Unnamed）的操作。&lt;/p&gt;

&lt;p&gt;Vim 提供了大致 10 类共 48 个寄存器。寄存器以 &lt;code&gt;&amp;quot;&lt;/code&gt; 开头进行标记，即 &lt;code&gt;&amp;quot;{register}&lt;/code&gt;。可以用 &amp;quot;{register}y 来拷贝到 {register} 中， 用 &amp;quot;{register}p 来粘贴 {register} 中的内容。如：&amp;quot;ayy 可以拷贝当前行到寄存器 a 中，而 &amp;quot;ap 则可以粘贴寄存器 a 中的内容。&lt;/p&gt;

&lt;p&gt;寄存器大致分为以下几类：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;匿名寄存器 &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;编号寄存器 &lt;code&gt;&amp;quot;0&lt;/code&gt; 到 &lt;code&gt;&amp;quot;9&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;小删除寄存器 &lt;code&gt;&amp;quot;-&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;26 个命名寄存器 &lt;code&gt;&amp;quot;a&lt;/code&gt; 到 &lt;code&gt;&amp;quot;z&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;3 个只读寄存器 &lt;code&gt;&amp;quot;:&lt;/code&gt;, &lt;code&gt;&amp;quot;.&lt;/code&gt;, &lt;code&gt;&amp;quot;%&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Buffer 交替文件寄存器 &lt;code&gt;&amp;quot;#&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;表达式寄存器 &lt;code&gt;&amp;quot;=&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;选区和拖放寄存器 &lt;code&gt;&amp;quot;*&lt;/code&gt;, &lt;code&gt;&amp;quot;+&lt;/code&gt;, &lt;code&gt;&amp;quot;~&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;黑洞寄存器 &lt;code&gt;&amp;quot;_&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;搜索模式寄存器 &lt;code&gt;&amp;quot;/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;动作/操作符/文本对象&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;动作&lt;/code&gt; 值移动光标的操作，如熟悉 h、j、k 和 l，以及 w 和 b 等，&lt;code&gt;/&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt; 也是一个动作。他们都可以搭配数字使用，比如 &lt;code&gt;2?the&lt;/code&gt; 可以将光标移动到倒数第二个 &amp;quot;the&amp;quot; 出现的位置。可以通过 &lt;code&gt;:h navigation&lt;/code&gt; 来查看支持的动作。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;操作符&lt;/code&gt; 是对某个区域文本执行的操作。如，d、~、gU 和 &amp;gt; 都是操作符。这些操作符既可以在普通模式下使用，也可以在可视模式下使用。在普通模式中，顺序是先按操作符，再按动作指令，比如 &amp;gt;j。在可视模式中，选中区域后直接按操作符即可，比如 Vjd。操作符也可以搭配数字使用，比如 2gUw 可以将当前单词以及下一个单词转成大写。由于动作和操作符都可以搭配数字使用，因此 2gU2w 与执行两次 gU2w 效果是相同的。有关操作符的详细帮助，可以通过 &lt;code&gt;:h operator&lt;/code&gt; 来查看。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;文本对象&lt;/code&gt; 是双向选择的文本（动作是单向选择的）。文本对象操作可以选中符号（比如括号、中括号和大括号等）标记的范围内文本，也作用于整个单词、整个句子等其他情况。文本对象不能用于普通模式中移动光标的操作，因为光标还没有智能到可以向两个方向同时跳转。但这个功能可以在可视模式中实现，因为在对象的一端选中的情况下，光标只需要跳转到另一端就可以了。可以通过 &lt;code&gt;:h text-objects&lt;/code&gt; 来详细了解关于文本对象的内容&lt;/p&gt;

&lt;p&gt;文本对象操作一般用 &lt;code&gt;i&lt;/code&gt; 或 &lt;code&gt;a&lt;/code&gt; 加上对象标识符操作，其中 &lt;code&gt;i&lt;/code&gt; 表示在对象内（英文 &lt;code&gt;inner&lt;/code&gt;）操作，&lt;code&gt;a&lt;/code&gt; 表示对整个对象（英文 &lt;code&gt;around&lt;/code&gt;）操作，这时开头和结尾的空格都会被考虑进来。如，diw 可以删除当前单词，ca( 可以改变括号以及括号中的内容。&lt;/p&gt;

&lt;p&gt;文本对象同样可以与数字搭配使用。比如，像 ((( ))) 这样的文本，假如光标位于最内层的括号上或最内层的括号内，那么 d2a( 将会删除从最内层开始的两对括号，以及他们之间的所有内容。其实，d2a( 这个操作等同于 2da(。需要注意的是，在 Vim 的命令中，如果有两处都可以接收数字作为参数，那么最终结果就等同于两个数字相乘。在这里，d 与 a( 都是可以接收参数的，一个参数是 1，另一个是 2，也可以把它们相乘然后放到最前面。&lt;/p&gt;

&lt;h2 id=&quot;part-6543118fb72&quot;&gt;配置&lt;/h2&gt;

&lt;p&gt;Vim 是一个可高度定制的编辑器，对编辑器的定制通过添加配置项和插件来完成，其读取配置文件的顺序可以通过：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;来查看，如以下为 MacOSX 上的结果：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;  system vimrc file: &quot;$VIM/vimrc&quot;
    user vimrc file: &quot;$HOME/.vimrc&quot;
2nd user vimrc file: &quot;~/.vim/vimrc&quot;
     user exrc file: &quot;$HOME/.exrc&quot;
      defaults file: &quot;$VIMRUNTIME/defaults.vim&quot;
 fall-back for $VIM: &quot;/usr/share/vim&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;一些配置示例：&lt;a href=&quot;https://github.com/kuanghy/vimconfig&quot;&gt;https://github.com/kuanghy/vimconfig&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;常用配置列举：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;&quot; 不要工作在 Vi 兼容的模式下
:set nocp

&quot; 显示不可视字符
:set list

&quot; 开启/取消粘贴模式
:set paste
:set nopaste

&quot; 显示/隐藏行号
:set number
:set nu
:set nonumber
:set nonu

&quot; 在搜索时忽略/不忽略大小写
:set ic
:set noic

:set fileencoding        &quot; 查看文件编码
:set fileencoding=utf-8  &quot; 转换文件编码

:set fileformat?         &quot; 查看文件格式
:set fileformat=unix     &quot; 设置文件格式

:set bomb?     &quot; 查询 BOM
:set bomb      &quot; 添加 BOM
:set nobomb    &quot; 删除BOM
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;配置 Vim 支持系统剪切板，首先查看 Vim 本身是否支持：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;vim --version | grep clipboard
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;输出的 clipboard 和 xterm_clipboard 前面为加号(+)表示支持，为减号(-)表示不支持。或者：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:echo has('clipboard')
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;输出 1 表示支持，输出 0 表示不支持。如果不支持可以尝试重新编译安装。支持系统剪切板后便可使用如下命令操作剪切板：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;&quot;+y 复制内容到系统剪切板
&quot;+p 把系统剪切板里的内容粘贴到 vim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;也可以配置 Vim 与系统剪切板共享复制粘贴（设置剪切板为匿名寄存器）：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;if has(&quot;clipboard&quot;)
    set clipboard=unnamed  &quot; copy to the system clipboard
    if has(&quot;unnamedplus&quot;)  &quot; X11 support
        set clipboard+=unnamedplus
    endif
endif
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;part-6542eef15a5&quot;&gt;移动&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;单位级&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;h&lt;/code&gt; 向左一字符&lt;/li&gt;
&lt;li&gt;&lt;code&gt;j&lt;/code&gt; 下一行&lt;/li&gt;
&lt;li&gt;&lt;code&gt;k&lt;/code&gt; 上一行&lt;/li&gt;
&lt;li&gt;&lt;code&gt;l&lt;/code&gt; 向右一字符&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;单词级&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;w&lt;/code&gt; or &lt;code&gt;W&lt;/code&gt; 向右移动到下一单词开头&lt;/li&gt;
&lt;li&gt;&lt;code&gt;e&lt;/code&gt; or &lt;code&gt;E&lt;/code&gt; 向右移动到单词结尾&lt;/li&gt;
&lt;li&gt;&lt;code&gt;b&lt;/code&gt; or &lt;code&gt;B&lt;/code&gt; 向左移动到单词开头&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;注：所有小写单词都是以分词符作为单词界限，大写字母以空格作为界限。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;块级&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;(&lt;/code&gt; 移动到当前句子开头&lt;/li&gt;
&lt;li&gt;&lt;code&gt;)&lt;/code&gt; 移动到下一句子开头&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{&lt;/code&gt; 移动到当前段落开头&lt;/li&gt;
&lt;li&gt;&lt;code&gt;}&lt;/code&gt; 移动到下一段落开头&lt;/li&gt;
&lt;li&gt;&lt;code&gt;+&lt;/code&gt; 移动到下一行开头&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-&lt;/code&gt; 移动到上一行开头&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gg&lt;/code&gt; 到文档第一行&lt;/li&gt;
&lt;li&gt;&lt;code&gt;G&lt;/code&gt; 到文档最后一行&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0&lt;/code&gt;, &lt;code&gt;|&lt;/code&gt; 到行首（第 1 列）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;^&lt;/code&gt; 到第一个非空白字符&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$&lt;/code&gt; 到行尾&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0nl&lt;/code&gt;, &lt;code&gt;n|&lt;/code&gt; 到当前行的第n 列&lt;/li&gt;
&lt;li&gt;&lt;code&gt;g_&lt;/code&gt; 到当前行的最后一个非空格字符处&lt;/li&gt;
&lt;li&gt;&lt;code&gt;H&lt;/code&gt; 到屏幕的首行&lt;/li&gt;
&lt;li&gt;&lt;code&gt;L&lt;/code&gt; 到屏幕尾行&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M&lt;/code&gt; 到屏幕中间&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%&lt;/code&gt; 到匹配的括号（包括小括号、中括号、大括号）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zt&lt;/code&gt; 将当前行移到屏幕顶部&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zz&lt;/code&gt; 将当前行移到屏幕中部&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zb&lt;/code&gt; 将当前行移到屏幕底部&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl-d&lt;/code&gt; 向下移动半页&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl-u&lt;/code&gt; 向上移动半页&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl-f&lt;/code&gt; 向下移动一页&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl-b&lt;/code&gt; 向上移动一页&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:&amp;lt;N&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;N&amp;gt;gg&lt;/code&gt; 跳转到第 N 行&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:+&amp;lt;N&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;N&amp;gt;j&lt;/code&gt; 向下跳 N 行&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:-&amp;lt;N&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;N&amp;gt;k&lt;/code&gt; 向上跳 N 行&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;注：&lt;code&gt;|&lt;/code&gt; 表示 bar 的意思，是普通模式下用于跳转到当前行某一列的一个命令 (To screen column [count] in the current line)，单个 | 表示当前行的第 0 列 (行首)。使用 0nl 跳转到指定列时，表示先用命令 0 将光标移动到行首，nl 表示执行 n 次向右移动光标操作；使用 n| 时，表示使用 | 命令跳转到当前行的第 n 列。&lt;/p&gt;

&lt;h2 id=&quot;part-6543056e195&quot;&gt;编辑&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;插入&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;执行插入操作需进入 插入模式，以下操作均可实现插入操作：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;i 在当前光标位置插入字符
I 在当前行首位置插入字符
o 在当前行往下插入新的一空行
O 在当前行往上插入新的一空行
a 在当前光标后追加字符
A 在当前行尾追加字符
r 替换当前字符
R 替换当前光标的字符直到退出插入模式（按ESC）
c 删除选中文本并进入插入模式
C 删除至行尾并进入插入模式
s 删除当前字符并进入插入模式
S 删除当前行并进入插入模式
:r filename 把文件的内容插入当前行的下一行
:r! command 把命令返回的结果插入到当前行的下一行
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;复制与粘贴&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;y&lt;/code&gt; (yanking)操作符用于复制文本，&lt;code&gt;p&lt;/code&gt; 操作符用于粘贴文本，以下列举常用的复制操作：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;yw 拷贝当前的一个单词
y0 拷贝的范围是当前光标处到行首
y^ 同上
y$ 拷贝的范围是当前光标处到行尾
yy 拷贝当前行
Y  同上
Nyy 从当前行开始拷贝 N 行
yf + 字符 复制从当前字符到指定字符
yG 拷贝当前行到文件尾
ygg 拷贝当前行到文件头
ggyG 复制整个文件
&quot;+y 复制到系统剪切板
&quot;+p 粘贴剪切板中的内容
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vim 还提供了基于底行命令模式的整行复制与移动命令：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:[range]co[py]{address}
:[range]t{address}

:[range]m[ove]{address}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;命令 copy 可以简写成 &lt;code&gt;:co&lt;/code&gt; 或者 &lt;code&gt;:t&lt;/code&gt;，命令 move 可以简写成 &lt;code&gt;m&lt;/code&gt;。示例：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:t5    拷贝当前行到第5行的下一行
:t.    拷贝当前行到光标下一行，相当于 `Yp` 或者 `yyp`
:t$    拷贝当前行到文件最后一行

:50,100move200    移动50行到100行的内容到第200行后面
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;删除/修改&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;x&lt;/code&gt; 操作符用于删除单个字符或选中的文本，&lt;code&gt;d&lt;/code&gt; 操作符用于删除单词、行、选中的文本等：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;x   删除当前光标处字符
X   删除光标所在前一个字符
dw  删除一个单词
de  删除到本单词末尾
dE  删除到本单词末尾包括标点在内
db  删除到前一个单词
dB  删除到前一个单词包括标点在内
d0  删除光标位置到本行开头
d$  删除从当前光标到行尾
D   同上
dd  删除一行
df + 字符  删除从当前字符到指定字符

# 删除括号或者引号中的内容
di(
di'
di&quot;

# 包括括号或者引号一起删除
da(
da'
da&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;c&lt;/code&gt; 操作符用于修改文本内容，即执行 c 操作时，会先删除选中的文本，然后再自动切换到插入模式：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;cw         修改一个单词
c$         修改从当前字符到行尾
cc         修改整行
C          修改当前光标至行尾
cf + 字符   修改从当前字符到指定字符

# 修改括号或者引号中的内容
ci(
ci'
ci&quot;

# 包括括号或者引号一起修改
ca(
ca'
ca&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;撤销/重做/合并行&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;u&lt;/code&gt; 撤销&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ctrl-r&lt;/code&gt; 重做&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;选中行，在执行 &lt;code&gt;J&lt;/code&gt; 操作符可合并多行到一行，默认合并当前行与下一行。&lt;/p&gt;

&lt;h2 id=&quot;part-6542f3cf5b0&quot;&gt;范围&lt;/h2&gt;

&lt;p&gt;在使用 Vim 的一些操作时，无非就两步，即先选择要操作的内容，在执行相应的操作。要操作的内容即是这里所说的 范围(Ranges)。可以使用 &lt;code&gt;:h cmdline-ranges&lt;/code&gt; 来查看有关命令操作范围的有关信息。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;大多数命令都可以加一个数字，用于指明操作范围&lt;/li&gt;
&lt;li&gt;范围可以是一个行号，用于指定某一行&lt;/li&gt;
&lt;li&gt;范围也可以是一对通过 &lt;code&gt;,&lt;/code&gt; 或 &lt;code&gt;;&lt;/code&gt; 分割的行号&lt;/li&gt;
&lt;li&gt;大部分命令，默认只作用于当前行&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:g[lobal]&lt;/code&gt; 默认会作用于所有行&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;范围的使用是十分直观的，以下是一些删除的例子（其中，&lt;code&gt;:d&lt;/code&gt;为 &lt;code&gt;:delete&lt;/code&gt; 的缩写）：&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align: left&quot;&gt;命令&lt;/th&gt;
&lt;th style=&quot;text-align: left&quot;&gt;操作范围&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:d&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;当前行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:.d&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;当前行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:1d&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;第一行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:$d&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;最后一行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:1,$d&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;所有行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:%d&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;所有行（这是 1,$ 的语法糖）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:.,5d&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;当前行至第 5 行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:,5d&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;当前行至第 5 行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:,+3d&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;当前行及接下来的 3 行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:1,+3d&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;第一行至当前行再加 3 行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:,-3d&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;当前行及向上的 3 行（Vim 会弹出提示信息，因为这是一个保留的范围）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:3,&amp;#39;xdelete&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;第三行至标注 为 x 的那一行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:/^foo/,$delete&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;当前行以下，以字符 &amp;quot;foo&amp;quot; 开头的那一行至结尾&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;:/^foo/+1,$delete&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;当前行以下，以字符 &amp;quot;foo&amp;quot; 开头的那一行的下一行至结尾&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;其中, &lt;code&gt;.&lt;/code&gt; 表示当前行，&lt;code&gt;$&lt;/code&gt;表示结束，&lt;code&gt;%&lt;/code&gt; 表示所有行，&lt;code&gt;-&lt;/code&gt; 与 &lt;code&gt;+&lt;/code&gt; 分别表示前后的偏移量。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;;&lt;/code&gt; 也可以用于表示范围。区别在于，&lt;code&gt;a,b&lt;/code&gt; 的 b 是以当前行作为参考的。而 &lt;code&gt;a;b&lt;/code&gt; 的 b 是以 a 行作为参考的。比如说，现在的光标在第 5 行。这时 &lt;code&gt;:1,+1d&lt;/code&gt; 会删除第 1 行至第 6 行，而 &lt;code&gt;:1;+1d&lt;/code&gt; 会删除第 1 行和第 2 行。&lt;/p&gt;

&lt;h2 id=&quot;part-6542ae8c794&quot;&gt;搜索&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;文档内查找&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;*&lt;/code&gt; 向后查找光标当前所在单词&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#&lt;/code&gt; 向前查找光标当前所在单词&lt;/li&gt;
&lt;li&gt;&lt;code&gt;g*&lt;/code&gt; 向后查找光标当前所在单词的字符序列，如当前单词为 foo 时，foobar 也会被找到&lt;/li&gt;
&lt;li&gt;&lt;code&gt;g#&lt;/code&gt; 向前查找光标当前所在单词的字符序列&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/&amp;lt;pattern&amp;gt;&lt;/code&gt; 向后查找指定字符串&lt;/li&gt;
&lt;li&gt;&lt;code&gt;?&amp;lt;pattern&amp;gt;&lt;/code&gt; 向前查找指定字符串&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在执行查找命令后，按 &lt;code&gt;n&lt;/code&gt; 会继续查找下一个，&lt;code&gt;N&lt;/code&gt; 会继续查找上一个。注意，n 和 N 是有方向性的，若之前通过 * 查找，则 n 会继续向文档尾方向查找，N 向文档首方向；反之，若你通过 # 查找，则 n 指向文档首，N 指向文档尾。&lt;/p&gt;

&lt;p&gt;在使用 &lt;code&gt;/&lt;/code&gt; 或 &lt;code&gt;?&lt;/code&gt; 查找时，加入 &lt;code&gt;\c&lt;/code&gt; 表示大小写不敏感查找，&lt;code&gt;\C&lt;/code&gt; 表示大小写敏感查找。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;行内查找&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;f&amp;lt;X&amp;gt;&lt;/code&gt; 当前行内向行尾方向查找并定位到字符 X&lt;/li&gt;
&lt;li&gt;&lt;code&gt;t&amp;lt;X&amp;gt;&lt;/code&gt; 当前行内向行尾方向查找并定位到字符 X 之前&lt;/li&gt;
&lt;li&gt;&lt;code&gt;F&amp;lt;X&amp;gt;&lt;/code&gt; 当前行内向行首方向查找并定位到字符 X&lt;/li&gt;
&lt;li&gt;&lt;code&gt;T&amp;lt;X&amp;gt;&lt;/code&gt; 当前行内向行首方向查找并定位到字符 X 之后&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在执行查找命令后，&lt;code&gt;;&lt;/code&gt; 继续向当前方向查找下一个字符，&lt;code&gt;,&lt;/code&gt; 向当前相反方向查找下一个字符。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;括号匹配查找&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;可以使用 &lt;code&gt;%&lt;/code&gt; 对 ( 和 )，[ 和 ]，{ 和 } 进行匹配查找，当光标位于其中一个 符号 上时，按下 %，光标会跳到与之匹配的另外一个符号上。&lt;/p&gt;

&lt;h2 id=&quot;part-6542cf956a1&quot;&gt;正则&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;元字符&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;. 匹配任意字符
[abc] 匹配方括号中的任意一个字符，可用-表示字符范围。如[a-z0-9]匹配小写字母和数字
[^abc] 匹配除方括号中字符之外的任意字符
\d 匹配阿拉伯数字，等同于[0-9]
\D 匹配阿拉伯数字之外的任意字符，等同于[^0-9]
\x 匹配十六进制数字，等同于[0-9A-Fa-f]
\X 匹配十六进制数字之外的任意字符，等同于[^0-9A-Fa-f]
\l 匹配[a-z]
\L 匹配[^a-z]
\u 匹配[A-Z]
\U 匹配[^A-Z]
\w 匹配单词字母，等同于[0-9A-Za-z_]
\W 匹配单词字母之外的任意字符，等同于[^0-9A-Za-z_]
\t 匹配&amp;lt;TAB&amp;gt;字符
\s 匹配空白字符，等同于[\t]
\S 匹配非空白字符，等同于[^\t]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;表示数量的元字符&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;注意：下面除了 &lt;code&gt;*&lt;/code&gt; 以外，其他都需要在前面加上 &lt;code&gt;\&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;*    匹配 0-任意个
\+   匹配 1-任意个
\?   匹配 0-1 个
\{n,m}   匹配 n-m 个
\{n}     匹配 n 个
\{n,}    匹配 n-任意个
\{,m}    匹配 0-m 个
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;表示位置的元字符&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$  匹配行尾
^  匹配行首
\&amp;lt;  匹配单词词首
\&amp;gt;  匹配单词词尾
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;需转义的字符&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;\*  匹配* 字符
\.  匹配. 字符
\/  匹配 / 字符
\\   匹配 \ 字符
\[  匹配 [ 字符
\]  匹配 ] 字符
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;在正则表达式中以 &lt;code&gt;\(&lt;/code&gt; 和 &lt;code&gt;\)&lt;/code&gt; 括起来的内容表示一个分组，在正则表达式后面使用的时候可以用 &lt;code&gt;\1&lt;/code&gt;、&lt;code&gt;\2&lt;/code&gt; 等变量（1、2 表示分组序号）来访问 &lt;code&gt;\(&lt;/code&gt; 和 &lt;code&gt;\)&lt;/code&gt; 中的内容。如 &lt;code&gt;\(foo\).*\1&lt;/code&gt; 可以配置 foo_bar_foo 等字符串。&lt;/p&gt;

&lt;p&gt;需要同时查找多个字符串，可以使用 &amp;quot;或&amp;quot; 运算符，即 &lt;code&gt;\|&lt;/code&gt;。如 &lt;code&gt;/foo\|bar&lt;/code&gt; 会同时查找 foo 和 bar 两个字符；再如 &lt;code&gt;/end\(if\|while\|for\)&lt;/code&gt; 匹配 &amp;quot;endif&amp;quot;，&amp;quot;endwhile&amp;quot; 和 &amp;quot;endfor&amp;quot; 字符串。&lt;/p&gt;

&lt;p&gt;在 Vim 中默认使用的搜索模式被称为 &lt;strong&gt;magic 模式&lt;/strong&gt;。在这种模式下，Vim 自动为某些额外的符号赋予特殊含义，例如 &lt;code&gt;.&lt;/code&gt; 、&lt;code&gt;*&lt;/code&gt;、&lt;code&gt;[&lt;/code&gt; 等。这种模式的初衷是想能在 Vim 中更容易地构造简单的正则表达式，但它却没能为诸如 &lt;code&gt;+&lt;/code&gt;、&lt;code&gt;?&lt;/code&gt;、&lt;code&gt;(&lt;/code&gt;、&lt;code&gt;)&lt;/code&gt;、&lt;code&gt;{&lt;/code&gt; 等符号赋予特殊含义，这些符号还必须经过转义才具有特殊含义。&lt;/p&gt;

&lt;p&gt;Vim 还提供了 &lt;strong&gt;very magic 搜索模式&lt;/strong&gt; 用于查找字符串，在这种模式下统一了所有特殊符号的规则：除下划线 &lt;code&gt;_&lt;/code&gt;、大小写字母以及数字 0 到 9 之外的所有字符都具有特殊含义。该模式使用 &lt;code&gt;\v&lt;/code&gt; 开启，如：&lt;code&gt;/\vend(if|while|for)&lt;/code&gt;，这样，用于为特殊字符进行转义的反斜杠字符便可以去掉，使得匹配表达式的可读性更强。如该种模式下，便可以用 &lt;code&gt;&amp;lt;&lt;/code&gt; 与 &lt;code&gt;&amp;gt;&lt;/code&gt; 符号表示单词定界符，而无需转义。&lt;/p&gt;

&lt;p&gt;此外，还有 &lt;strong&gt;very nomagic 搜索模式&lt;/strong&gt;，在该模式中有且只有反斜杠 &lt;code&gt;\&lt;/code&gt; 具有特殊意义，即消除了附加在 &lt;code&gt;.&lt;/code&gt;、&lt;code&gt;*&lt;/code&gt; 以及 &lt;code&gt;?&lt;/code&gt; 等大多数字符上的特殊含义。也就是绝大多数字符都按原义进行查找匹配，该模式使用 &lt;code&gt;\V&lt;/code&gt; 开启。如要查找 a.k.a. 字符串时，如果不使用 very nomagic 模式搜索，则其他的字符串也可能被找到，如 backward，除非使用转义 &lt;code&gt;/a\.k\.a\.&lt;/code&gt;。而使用 very nomagic 模式就要简单得多 &lt;code&gt;/\Va.k.a.&lt;/code&gt;。
`&lt;/p&gt;

&lt;h2 id=&quot;part-6542bc2fd1a&quot;&gt;替换&lt;/h2&gt;

&lt;p&gt;Vim 中的简单替换可以使用 &lt;code&gt;r/R&lt;/code&gt;、&lt;code&gt;c/C&lt;/code&gt;、&lt;code&gt;s/S&lt;/code&gt; 等操作符：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;r  替换当前字符
R  替换当前光标的字符直到退出替换模式（按ESC）
cw  替换当前单词
cc  替换当前行，相当于 S
C   替换当前位置到行尾，相当于 c$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;此外，还可以使用 &lt;code&gt;:s&lt;/code&gt; (substitute)操作，配置范围、模式查找等实现更加强大的替换功能，其格式为：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;[range]s/{pattern}/{string}/[flags]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;flags 有如下四个选项&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;c&lt;/code&gt; confirm，每次替换前询问&lt;/li&gt;
&lt;li&gt;&lt;code&gt;e&lt;/code&gt; error，不显示错误&lt;/li&gt;
&lt;li&gt;&lt;code&gt;g&lt;/code&gt; globle，不询问，整行替换。如果不加 g 选项，则只替换每行的第一个匹配到的字符串&lt;/li&gt;
&lt;li&gt;&lt;code&gt;i&lt;/code&gt; ignore，忽略大小写&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;可以同时使用多个 flag，如 cgi 表示不区分大小写，整行替换，替换前询问。示例：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:1,10s/from/to/g  表示在第1到第10行（包含第1，第10行）之间搜索替换
:10s/from/to/g  表示只在第10行搜索替换
:%s/from/to/g  表示在所有行中搜索替换
:1,$s/from/to/g  同上

:%s/\s+$//g  删除行尾空格
:%s/^\s*// 或 :%s/^ *//  删除行首多余空格
:%s/^$// 或 :g/^$/d  删除沒有內容的空行
:%s/^\s*$// 或 :g/^\s*$/d  删除包含有空格组成的空行
:%s/^[ |\t]*$// 或 :g/^[ |\t]*$/d  删除以空格或 tab 开头到结尾的空行
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;part-6542bfecf38&quot;&gt;标记&lt;/h2&gt;

&lt;p&gt;标记 可以理解为 书签，在某处打上标记后，可以快速从别处跳转回来。标记可以分为三类：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a-z 用户设置，仅对当前的一个文件生效，也就意味着只可以在当前文件中跳转&lt;/li&gt;
&lt;li&gt;A-Z 用户设置，全局标记，可以作用于不同文件。大写标注也称为「文件标注」。跳转时有可能会切换到另一个缓冲区&lt;/li&gt;
&lt;li&gt;0-9 由 viminfo 记录，0 代表 viminfo 最后一次被写入的位置。实际使用中，就代表 Vim 进程最后一次结束的位置。1 代表 Vim 进程倒数第二次结束的位置，以此类推&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;定义一个标记用 &lt;code&gt;m&lt;/code&gt; 操作符，如 &lt;code&gt;ma&lt;/code&gt; 标记当前问题为 a 标记。在标记间跳转用 &lt;code&gt;&amp;#39;&lt;/code&gt; / &lt;code&gt;g&amp;#39;&lt;/code&gt; 或者 &lt;code&gt;`&lt;/code&gt; / &lt;code&gt;g`&lt;/code&gt; 加上标注名。单引号与倒引号的区别在与，单引号会跳转回被标记行的第一个非空字符，而倒引号会跳转回被标记行的被标记列。&lt;/p&gt;

&lt;p&gt;还有一些其他的跳转方式：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;'[ 与 `[    上一次修改或复制的第一行或第一个字符
'] 与 `]    上一次修改或复制的最后一行或最后一个字符
'&amp;lt; 与 `&amp;lt;    上一次在可视模式下选取的第一行或第一个字符
'&amp;gt; 与 `&amp;gt;    上一次在可视模式下选取的最后一行或最后一个字符
'' 与 `'    上一次跳转之前的光标位置
'&quot; 与 `&quot;    上一次关闭当前缓冲区时的光标位置
'^ 与 `^    上一次插入字符后的光标位置
'. 与 `.    上一次修改文本后的光标位置
'( 与 `(    当前句子的开头
') 与 `)    当前句子的结尾
'{ 与 `{    当前段落的开头
'} 与 `}    当前段落的结尾
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;标记也可以搭配 范围 一起使用。如果在可视模式下选取一些文本，然后按下 &lt;code&gt;:&lt;/code&gt;，这时命令行会被填充为 &lt;code&gt;:&amp;#39;&amp;lt;,&amp;#39;&amp;gt;&lt;/code&gt;，这即表示在可视模式下选取的范围。&lt;/p&gt;

&lt;p&gt;使用 &lt;code&gt;:marks&lt;/code&gt; 可以查看当前所有的标记，使用 &lt;code&gt;:h mark-motions&lt;/code&gt; 更多关于标记的帮助信息。&lt;/p&gt;

&lt;h2 id=&quot;part-3786d407a349d2d&quot;&gt;寄存器&lt;/h2&gt;

&lt;p&gt;寄存器主要用于存储文本内容，其为复制粘贴功能提供辅助。寄存器的访问和操作使用冒号 &lt;code&gt;&amp;quot;&lt;/code&gt; 作为前缀，如 &lt;code&gt;&amp;quot;ayy&lt;/code&gt; 表示复制当前行到 a 寄存器，&lt;code&gt;&amp;quot;ap&lt;/code&gt; 表示粘贴寄存器中的内容。使用 &lt;code&gt;:reg&lt;/code&gt; 可以查看当前所有寄存器中的内容，使用 &lt;code&gt;:reg &amp;quot;{register_name}&lt;/code&gt; 可以查看指定寄存器的内容。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;匿名寄存器(Unnamed)：&lt;/strong&gt; 保存最近一次的复制或删除操作 (d, c, s, x, y)。如果当前使用的 vim 版本支持剪切板，则可以将匿名寄存器定向到剪切板上，这样便可以与系统共享剪切板：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;set clipboard=unnamed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;编号寄存器(Numbered)：&lt;/strong&gt; 即以数字命令的寄存器，从 &lt;code&gt;&amp;quot;0&lt;/code&gt; 到 &lt;code&gt;&amp;quot;9&lt;/code&gt; 共 10 个。其中 &lt;code&gt;&amp;quot;0&lt;/code&gt; 保存着最近一次复制的内容，&lt;code&gt;&amp;quot;1&lt;/code&gt; 到&lt;code&gt;&amp;quot;9&lt;/code&gt; 保存着删除掉的字符串。 删除操作符包括 s, c, d, x。 删除掉的字符串会被存到 &amp;quot;1 中，上次删除的则会被存到 &amp;quot;2 中，以此类推。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;小删除寄存器(Small delete)：&lt;/strong&gt; 保存最近一次行内删除的内容，如 &lt;code&gt;dw&lt;/code&gt; 删除一个词，&lt;code&gt;d9l&lt;/code&gt; 删除 9 个字符，&lt;code&gt;cb&lt;/code&gt; 向前更改一个词等。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;命名寄存器(Named)：&lt;/strong&gt; 其有 &lt;code&gt;&amp;quot;a&lt;/code&gt; 到 &lt;code&gt;&amp;quot;z&lt;/code&gt; 共 26 个，这类寄存器只有在被指定时才会被定义和使用。其实在录制宏时，所有键盘操作会以字符串的形式存到寄存器中。需注意的是，寄存器名也可以为大写，当使用小写字母进行操作时会覆盖当前寄存器内容，而当使用大写字母进行操作时会追加当前寄存器内容。如 &lt;code&gt;&amp;quot;Ayy&lt;/code&gt; 会复制当前行并追加到寄存器 a 中。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;只读寄存器(Read-only)：&lt;/strong&gt; 共有 3 个只读寄存器，其值是由 Vim 提供，不允许改变：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;quot;.&lt;/code&gt;：最近一次 insert 模式中插入的文本。注意 &lt;code&gt;.&lt;/code&gt; 命令用于重复上次操作，而 &lt;code&gt;&amp;quot;.&lt;/code&gt; 用于存储上次插入&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;quot;%&lt;/code&gt;：当前文件名，不是全路径，也不是纯文件名，而是从当前 Vim 的工作目录到该文件的路径，即相对路径&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;quot;:&lt;/code&gt;：最近一次底行命令模式下使用的命令。正如 &lt;code&gt;@a&lt;/code&gt; 可以执行 &lt;code&gt;&amp;quot;a&lt;/code&gt; 寄存器中的宏一样，&lt;code&gt;@:&lt;/code&gt; 可以执行上次命令&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;交替文件寄存器(Alternate buffer)：&lt;/strong&gt; 交替文件寄存器 &lt;code&gt;&amp;quot;#&lt;/code&gt; 存储着当前 Vim 窗口（Window）的交替文件。交替文件是指 Buffer 中的上一个文件，可通过 &lt;code&gt;Ctrl+^&lt;/code&gt; 来切换交替文件与当前文件。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;表达式寄存器(Expression)：&lt;/strong&gt; 表达式寄存器 &lt;code&gt;&amp;quot;=&lt;/code&gt; 主要用于计算 Vim 脚本的返回值，并插入到文本中。当键入 &lt;code&gt;&amp;quot;=&lt;/code&gt; 后光标会移动到命令行，此时可以输入任何 Vim 脚本的表达式，例如 3+2，按下回车并且 p 则会得到 5。这对于调试 Vim 脚本是非常有用的，比如调用一个函数看它是否有正确的返回值。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;选择(Selection)和拖放(Drop)寄存器：&lt;/strong&gt; 包括 &lt;code&gt;&amp;quot;*&lt;/code&gt;, &lt;code&gt;&amp;quot;+&lt;/code&gt;, 和 &lt;code&gt;&amp;quot;~&lt;/code&gt;，这三个寄存器的行为是和 GUI 相关的。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;quot;*&lt;/code&gt; 和 &lt;code&gt;&amp;quot;+&lt;/code&gt; 在 Mac 和 Windows 中，都是指系统剪切板（clipboard），例如 &lt;code&gt;&amp;quot;*yy&lt;/code&gt; 即可复制当前行到剪切板。 以供其他程序中粘贴。其他程序中复制的内容也会被存储到这两个寄存器中。 在X11系统中（绝大多数带有桌面环境的Linux发行版），二者是有区别的：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;quot;*&lt;/code&gt; 指 X11 中的 PRIMARY 选区，即鼠标选中区域。在桌面系统中可按鼠标中键粘贴。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;quot;+&lt;/code&gt; 指 X11 中的 CLIPBOARD 选区，即系统剪切板。在桌面系统中可按 Ctrl+V 粘贴。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;拖放寄存器 &lt;code&gt;&amp;quot;~&lt;/code&gt; 是只读的，当有文本拖拽到 Vim 时，被拖拽的文本被存储在 &lt;code&gt;&amp;quot;~&lt;/code&gt; 中。Vim 默认的行为是将 &lt;code&gt;&amp;quot;~&lt;/code&gt; 中内容插入到光标所在位置。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;黑洞寄存器(Black hole)：&lt;/strong&gt; 所有删除或拷贝到黑洞寄存器 &lt;code&gt;&amp;quot;_&lt;/code&gt; 的文本将会消失，这是为了在删除文本的同时不影响任何寄存器的值，其通常用于 Vim 脚本中。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;搜索寄存器(Last search pattern):&lt;/strong&gt; 搜索寄存器 &lt;code&gt;&amp;quot;/&lt;/code&gt; 用于存储上一次搜索的关键词，即最近一次通过 &lt;code&gt;/&lt;/code&gt;、&lt;code&gt;?&lt;/code&gt; 或 &lt;code&gt;:global&lt;/code&gt; 等命令调用的匹配条件。该寄存器是可写的，例如: &lt;code&gt;let @/ = &amp;quot;harttle&amp;quot;&lt;/code&gt; 将会把 &amp;quot;harttle&amp;quot; 写入该寄存器。下次搜索时不输入搜索词直接回车便会搜索 &amp;quot;harttle&amp;quot;。&lt;/p&gt;

&lt;h2 id=&quot;part-b8a9807&quot;&gt;宏&lt;/h2&gt;

&lt;p&gt;在 Vim 中可以录制一系列按键动作，并把他们存储到寄存器中，这便是 &lt;strong&gt;宏&lt;/strong&gt;。宏是一系列操作的集合，它可以将一些复杂的操作进行记录，之后可以进行回放。&lt;/p&gt;

&lt;p&gt;操作符 &lt;code&gt;q&lt;/code&gt; 用于开启或结束宏录制，按 &lt;code&gt;q{register}&lt;/code&gt; 开始进入录制，然后再按 &lt;code&gt;q&lt;/code&gt; 可结束录制。如果要对宏进行回放，按 &lt;code&gt;@{register}&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;示例一，在行末加分号，命令为：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;qa
$a;&amp;lt;Esc&amp;gt;j$，
q
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;命令的含义是：开启宏录制，并记录到寄存器 a 中，先移动到行尾，然后在行尾插入分号，接着退到普通模式，再把光标移动到下一行的末尾，最后结束宏录制。录制结束后，输入 &lt;code&gt;@a&lt;/code&gt; 便会执行宏中的操作，&lt;code&gt;5@m&lt;/code&gt; 表示重复执行 5 次宏操作。&lt;/p&gt;

&lt;p&gt;示例二，从 1 到 100，每行 +1，首先在第一行插入 1，然后光标定位到第一行的 “1” 上，执行宏录制：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;qb
yyp&amp;lt;Ctrl&amp;gt;a
q
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;命令的含义是：开始录制宏到寄存器 b 中，&lt;code&gt;yy&lt;/code&gt; 复制当前行，&lt;code&gt;p&lt;/code&gt; 粘贴到下一下， &lt;code&gt;&amp;lt;Ctrl&amp;gt;a&lt;/code&gt; 让当前光标所在数字加 1。然后执行 &lt;code&gt;98@b&lt;/code&gt; 将宏回访 98 遍即可实现将数字加到 100。&lt;/p&gt;

&lt;h2 id=&quot;part-65427dac75a&quot;&gt;其他&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;插入计算结果&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;在插入模式下，输入 &lt;code&gt;ctrl-r =&lt;/code&gt;，然后输入表达式，就能在光标处得到计算结果。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;保存无权限的只读文件&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;如果打开了一些没有权限编辑的只读文件，并修改了内容，且希望对修改进行保存时，可以用如下命令（&lt;strong&gt;前提是当前用户有 sudo 权限&lt;/strong&gt;）：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:w !sudo tee %
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;高亮普通文件&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;有的文件可能没有后缀（扩展名），Vim 无法识别文件类型，所以也无法进行语法高亮，此时可以手动设置文件的类型，以开启语法高亮。如设置文件类型为 shell 脚本类型：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:set filetype=sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;编辑远程文件&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vim 内置的插件 netrw 支持对远程文件的编辑。它的原理是将远程的文件通过 scp 复制到本地的临时文件中，再用这个文件打开一个缓冲区，然后在保存时再将文件复制回远程位置。以下命令列举在本地打开 SSH 远程服务器上文件的方式：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:e scp://user@remotehost/.vimrc

:e scp://user@remotehost/~/.vimrc

:e scp://user@remotehost//etc/passwd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;也可以配置 &lt;code&gt;~/.ssh/config&lt;/code&gt; 文件，使得命令更加简单，如 ~/.ssh/config 存在如下配置：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;Host test
    HostName test.site.com
    Port 23456
    User test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;那么编辑文件的命令就可以变得很简单：&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:e scp://test/.vimrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;查看安装的所有脚本&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;:scriptnames
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;有用的快捷键&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;K    打开光标所在词的 manpage
.    重复上一次的操作，如 dd 删除一行后，. 命令可继续执行删除
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;part-65428734206&quot;&gt;参考&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vim.rtorr.com/lang/zh_cn&quot;&gt;Vim Cheat Sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/wsdjeg/vim-galore-zh_cn&quot;&gt;https://github.com/wsdjeg/vim-galore-zh_cn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://liuzhijun.iteye.com/category/270228&quot;&gt;https://liuzhijun.iteye.com/category/270228&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.csdn.net/LEON1741/article/details/54314053&quot;&gt;https://blog.csdn.net/LEON1741/article/details/54314053&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://harttle.land/2016/07/25/vim-registers.html&quot;&gt;https://harttle.land/2016/07/25/vim-registers.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://weirping.coding.me/blog/Regex-in-Vim.html&quot;&gt;http://weirping.coding.me/blog/Regex-in-Vim.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vimjc.com/vim-very-magic.html&quot;&gt;https://vimjc.com/vim-very-magic.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 23 Nov 2019 00:00:00 +0800</pubDate>
        <link>https://donothing.site/2019/11/23/vim-skill/</link>
        <guid isPermaLink="true">https://donothing.site/2019/11/23/vim-skill/</guid>
        
        <category>vim</category>
        
        
        <category>文本编辑</category>
        
      </item>
    
  </channel>
</rss>
