[toc]

饱食穷民封面

《饱食穷民》是一本纪实文学题材,在日本上市已经有近二十五年的时间,书中所述的事情也已经过去了三十多年,但是又和中国现在发生在我们身边的一些社会现象有着惊人的相似之处,比如小微借贷加班厌食等,这在 30 多年前的日本已经司空见惯。

读这本书,可以通过时空错位来借鉴 20 多年前发生在日本的事情,现在也发生在我们身边。以史为镜,可以照出我们自己得与失,值得我好好思考和借鉴。

作者简介

本书的作者,斋藤茂男,是日本著名新闻记者,同时也是一名广为人知的纪实文学作家。在以超人般的精力从事记者工作的同时,作者至一九九四年间由岩波书店出版的十二本纪实文学作品集《日本世相》系列,不仅是他从二十世纪七十年代到九十年代记者生涯的集大成之作,同时也是一幅刻画了日本社会从经济高速增长时期直到泡沫经济破灭的真实写照。这本《饱食穷民》是纪实文学《日本世相》系列的作品之一。

时代背景

这本《饱食穷民》所记录的时代背景,正是二十世纪八十年代中期到九十年代的这段时间。在这个时期,日本成功挺过石油危机、日元升值等一连串的 “国难”,还化 “国难” 为动力,成功收获众多世界第一的勋章,跃居超级经济大国之列。

在欣欣向荣的表象下,作者通过一系列的采访,描述了社会底层的人民虽然解决了温饱问题,但是却在借贷、加班和厌食中痛苦,不知满足,迷失了自己。


注:文章后面的内容大部分摘录自《饱食穷民》,MC 后面的内容是我新增的。

关于《日本世相》

饱食穷民描述的时代和现在的中国很像,经济高速发展,房价飞涨,跃居超级经济大国之列。那个阶段,所有人都陷入一个巨大装置,努力把时间变为金钱,被强迫着,要更快、更有效率地活着,哪怕超越身体极限,时时刻刻,一分一秒都不能错过。这节奏让我们无法按照自然时间生活,过有生命力的生活,只感觉身心俱疲,不停被压榨。

  • MC: 我使用 阶段 这个名词来描绘 20 年前的日本,因为我认为这可能是每一个国家崛起的必经过程,和时间的关系并不大。

序章 走向世纪末

  • 洛克希德事件案发,日本首相田中角荣被捕。
    • MC:洛克希德公司是当时美国最大的飞机制造公司和军火供应商之一,该公司主要是依靠行贿打开国外市场的,因此,美国的许多飞机制造商向美国参议院外交委员会跨国公司小组进行了举报。日本检察官从中发现了一张领受人为田中角荣的 5 亿日元的收据。法院认定田中角荣违犯外汇法、受托受贿,判处其四年徒刑,罚金 5 亿日元。这起日本历史上旷日持久的马拉松审判,在历时 19 年,耗资 6 亿日元后,终于落下帷幕。
  • 苏联切尔诺贝利核电站事故发生,世界陷入不安。
    • MC:切尔诺贝利核电站位于前苏联基辅市北 130 公里的地方,是前苏联 1973 年开始修建,1977 年启动的最大的核电站。1986 年 4 月 26 日,世界上最严重的核事故在苏联切尔诺贝利核电站发生。
  • 1987 年房价一年飙升三倍。日本国营铁道和日本航空民营化改革。空前的理财热潮,股价暴跌。
    • MC: 这个阶段可能类似于 08 ~ 15 年的中国,房地产价格飞涨。
  • 以新增消费税为主要内容的税收改革法案在临时国会获通过。经济以内需为中心持续走高
    • MC: 现在的中国提出 “构建以国内大循环为主体、国内国际双循环相互促进的新发展格局”,貌似和这个阶段相似。现在的房地产已经耗干了每个家庭的消费能力,经济内需怎么促进呢?现阶段的反垄断、数字税等,是否可以算作消费税的另一种形式呢?
  • 德国实现统一,正式结束分裂历史。
    • MC:1990 年发生的事情,东德西德统一,距离我们并不遥远。

不会珍爱自己的人们

  • 脑子聪不聪明,学习、工作成绩好不好,有没有能力迅速完成任务,对公司有没有贡献…… 他们内心的刑具,就是这些丈量、判断个体价值高低的价值观、人生观。也可以说,正是这些价值观建构的体系驱赶着人们陷入无限竞争的社会

人吃人的画卷

  • 这无疑让人联想到这样一幅画面:竞争和生产效率至上主义的齿轮正奏响嘎吱嘎吱的旋律,日夜压榨着每一个人
    • MC:能否对应到现在 “降本增效” 的阶段。裁员的压力下,每一个人被 KPI 压得喘不过气来。
  • 如今,私营电视台也纷纷推出《直播到天明》这种深夜节目,满街都是 24 小时营业的便利店,整个社会都逐渐朝着 “24 小时不夜城” 方向发展。就像纽约、伦敦等大都市一样,成功跻身国际金融中心之列的东京在信息、经济上和国外往来越来越紧密。由于时差的关系,越来越多的写字楼到了夜晚也灯火通明。

  • 本应以改善公司业务为目的的微电子化,反而将前所未有的高精度管理的手段指向了公司员工。效率至上的管理系统创造出巨大财富的生产系统,开始了对人类的报复。第一盏红灯,亮给了人类的健康。

    • 我们就像是骑在一辆随时会倒下的独轮车上,感受到背后不断逼近的不安,非得骑到把自己累倒,不死不休。
  • 现在是寻呼机时代。计算机技术人员无论假期还是深夜,都会因为机器故障和维护被叫去公司工作。

    • MC: 现在手机时代,不限于程序员,打工人正常的休息都没有了。
  • 少数资产家把持着一路狂涨的土地,贪得无厌地增殖手中的资产,导致贫富差距越拉越大。
    • 在这样一个挥汗劳动不如坐收利息的社会,人心没有不走向疯狂的道理。

饱食穷民

无处可逃的男人

  • 公司每年都会制定更高的目标,我们每年都必须超额完成公司的目标才行。在这种制度下,无论你怎么拼命,都永远不会有解脱的那天。

  • 小微贷为了多收利息,放款的数额通常大于借款人申请的金额。

    • 放款人通常会通过抬举借款人的方式,麻痹他们的神经,怂恿他们多借,最后酿成严重的后果。
      • MC: 这种做法在现在的小微贷款也很普遍,互联网平台总是会借给你更多的钱,额度远远超过你的需求。
  • 这些公司打着‘XX 大作战’的旗号,喊出大家齐心协力达成目标之类的口号,或是提高士气,或是鼓励员工互相竞争,甚至在公司内制造出员工皆兄弟这种氛围,这其实也是人力管理的方法之一。

    • 归根结底,在这种所有员工‘人人有责’的制度中,一旦一个人遭遇失败,就会陷入严重的孤独感和失落感之中,认为自己给同事造成了麻烦和损失,从而产生自责的情绪。
  • 公司在不停强调要我们 “学会独立思考”,但每天都被销售指标穷追不舍的员工,又哪里有时间读书、思考呢?

梦想之城

  • 在父亲的劝说下,祐二郎中学毕业后,也不得不过上了烧炭挣钱的日子。每天早上五点起床之后,要走上两个小时的山路。弟弟砍树,把树干锯成一段一段的,哥哥去炭窑把锯好的木头烧成炭。烧好的炭,每十五公斤捆成一大捆,然后每个人背四捆下山。年纪才十五岁的少年本来身体就不壮实,要背负六十公斤的木炭下山,其中辛苦,可想而知。每走两三百米,就要靠在石头上休息一次,喘过气来后再走两三百米…… 如此循环往复。

  • 工作第二年,他把母亲接到东京来旅游。看着满面笑容的母亲,他心里得意极了。

  • 从某些角度看,保险合同总量的激增正反映了人们心中的不安

我要买!买!买!

  • 信贷消费真正开始快速增长,其实是在石油危机后的低增长时代。不光卖方需要变本加厉地提升市场的消费欲望,买方也是,一方面面临实际收入的减少,而另一方面却希望维持现有生活和消费水平,不愿让步

    • 咱们都生活在大量消费的社会之中,刺激欲望的宣传像洪水一样席卷着我们。面对这一大潮,我们甚至来不及思考就被卷入其中。
    • MC:中国逐步进入低增长时代,现在内循环是经济主要增长动力;那么,社会和政府也会不遗余力地促进消费,但是我们要限制借贷消费,警惕实际购买能力下降。
  • 我们公司的主要业务是销售和租赁复印机。在这次出事之前,公司和一家信贷公司达成合作,信贷公司给我们介绍客户,而我们公司的员工需要用他们公司的信用卡。

  • 很多女性平时心中都有一种空虚感,不断寻求能够满足自己的东西。有时候刚好赶上身体状态的变化,就很容易无法控制购物消费的冲动,会大量购买衣服等物品。这种心理,有时候还会以别的形式体现出来,比如喝酒、吃东西等。

    • 夫妻关系虽然表面上很好,甚至看上去十分融洽,但其实妻子想要和丈夫享受更多二人世界的需求却不能实现,又没办法率直坦诚地向丈夫表达心中的诉求。还有就是夫妻关系整体十分淡薄,没有构成两人相互支撑的关系。这时,妻子就很容易变得需要依靠物质来填补心中的空虚。

美满生活

  • 虽然像我这样的人根本算不上什么中产阶级,但我心中多少总有一些仿佛是中产阶级般的感觉。想着既然别人都去夏威夷,那我也得去夏威夷。别人有的东西,我当然也想买,别人去旅游,那我也得去旅游,想过上高质量的生活…… 你说对吧?我承认确实有虚荣心在里面。
    • MC:警惕陷入消费危机,中产陷阱。消费不攀比,量入为出。
  • 一开始,我对她还有一些不解和轻蔑,认为这个女人的金钱观和脑子都有问题,然而听着她的倾诉,又渐渐觉得她就像一个身坠陷阱的小动物,沉湎于虚假繁荣的生活中不能自拔,甚至开始对她抱有一些同情。

X 先生的对话

  • 所谓‘细民’,是指有固定工作的社会底层的一般工人阶层。‘贫民’是属于没有固定工作的城市杂工阶层。而‘穷民’,则是指老弱病残等无力维持生计的赤贫阶层。
  • 究竟贫困在哪些方面呢?
    • 首先,是在经济上没有可以依靠的储蓄。
      • 缺少‘储蓄’的不安,还有另一层意义。一个人从根本上赖以生存的最终手段 -- 技术、技能、知识、判断能力,也许一夜之间就会被彻底推翻。现代人心中的这种不安,都在日渐膨胀。
    • 物质和精神的双重折磨,是现代贫困的一大特征。
  • 现代社会中能够作为滋润人的 “水”,换而言之对人们来说最为重要的又是什么呢?X 先生这样告诉我们:“我们所在的资本主义社会中,企业既无情也无义,只会一味追求利益,这个社会中,资本一面不停增值,一面彼此之间还会不断竞争。刺激企业追求利益的冲动、经济的冲动不停侵蚀人们的生活,压垮、吞噬并统治生活本身…… 我认为,这就是当今社会的特质。
    • 就连我们的生活,也遭到了经济原理的彻底占领…… 所以,人们开始变得像企业一样对经济活动愈发敏感,甚至可以说人类已经被改造成了金钱和物质统治下的行尸走肉。所谓经济活动原本是指人们曾经为了糊口而进行的耕田、狩猎等为生活动。虽然经济是支撑人们生活的重要基础,但其本身不是我们活着的目的
  • X 先生说,生活第一,经济是支撑生活的基础 -- 这本应该是再理所当然不过的道理,然而不知不觉之间,已经变得本末颠倒,因此我们有必要对其进行重新审视。
  • 拓展自己的能力、不断成长发展,满足实现自我的欲望。
  • 如果每个人的个人世界中,不能够充分地、均衡地满足上述多种多样的欲望,那么无论我们的宪法多么强调和平和人权的重要性,我们也会忘记是非善恶,忘记我们应该齐心协力实现的目标,无法做出正确的判断。我们在战争中付出了惨烈的代价才得到的民主主义,不就是为了让每个人都能够发展自己的人性、实现幸福生活的国家体制吗?

快节奏的城市

魔性附身

  • 巴士里塞满了一看便知是 “高科技战士” 的上班族。他们把公文包垫在膝盖上,手里举着经济类报纸,耳朵里插着耳机,一言不发…… 这就是现在随处可见的、面目整齐划一的男人们的生活状态。

  • 公司将系统工程师和程序员等精锐部队调集于此,再加上外包公司派来的援军,以人海战术来推进这个项目。

  • 技术应激(technostress):这个词最早来自美国临床心理学家克雷格・布罗德(Craig Brod)所提出的的概念。这一概念本来有两个意思:
    • 一是指中老年人对于计算机的排斥症状。现在,各个公司都争相导入计算机办公系统,很多人跟不上计算机化的脚步,但又不得不用计算机办公…… 对于计算机的不安、恐怖,给他们带来了很大的心理压力。
      • 但是最近几年,这种 “计算机排斥症” 不断减少,反而是人们对计算机的过度适应症状开始显现出来。
  • 系统工程师们的宿命,就是面对性格冥顽不灵又不知变通的计算机,在终端的屏幕前一边自问自答,一边重新组织逻辑关系、修改错误,孤身奋战。问题解决、计算机正常工作后的成就感就越大。每当这时,“冥顽不灵的倔老头” 仿佛摇身一变,成了 “顺从又听话的老好人”。好多人都说 “对机器越来越爱不释手”,或是有 “人马合一的快感”。估计就是这种感觉。
    • 当人和计算机之间产生了上面这种亲密关系后,每当离开计算机,人心中都会产生不安。这种对计算机过度适应的心理状态,就是所谓的技术应激。
      • 没有感情、无论何时都会正确无误地回应人类的计算机,就会比受感情左右的人类好处得多。相比之下,人际交往就会显得越发麻烦。这样发展的结果,就是越来越厌恶和人交往,逐渐走向自闭,失去鲜活水润的感情
  • 如果出现问题,就会停下来思考,然后再次输入自己设计的逻辑,电脑马上又会输出结果。这种你来我往的过招实在太有趣了,渐渐地,这种趣味就会像毒品一样作用于你的身体。这样一来,无论你在终端机前坐几个小时,身体都不会觉得疲劳。只要是软件技术人员,无论是谁几乎都会有相同的感觉。
  • 计算机领域的工作一方面富于创造性和趣味性,另一方面却无时无刻都需要面对被时代追赶的压力。
    • 开发计算机软件的工作会刺激人对知识的好奇心,独具趣味。不仅如此,每名工程师编程都有其独特的个性,如果有一百名工程师同时开发一个系统,那这个系统中就会有一百种独具个性的程序。软件开发就是这样一种富于创造性和个性的工作。
    • 每个工程师都要面对自身技术落后于时代的不安编程是一项十分麻烦的工作,所以才会有人说,工程师三十五岁就得退休。工程师拼的不光是知识,到最后决定胜负的其实是腕力和体力。
      • MC: 现在流行的程序员 35 岁就退休,原来在 80 年代就已经在日本流行起来。
  • 计算机的世界里,不是 1 就是 0,不是正确就是错误,不是黑就是白。所谓的‘中间’‘灰色’‘暧昧地带’是不存在的。
    • 从早到晚面对计算机,在沉重的心理压力下,连思考方式都要和机器合一。
  • 将浪费压缩到最低,不断寻求到达目标的捷径。越是陷入这种思考模式,和计算机的对话就越是顺利。但是,这样却会导致和人的交往越发空虚、冷漠。
    • 这样下去的话,和其他人的交往就会越来越少,视野也会越来越窄。大家的脑子有九成都被电脑占领了,对于政治、社会之类的越发淡漠,至于文学、戏剧什么的就更是像火星人的活动,连想都不会去想。这样每天都面对计算机,虽然技术会有所提高,但作为一个人是没有成长的

人心的变化

  • 计算机的世界里,一切不合逻辑的事情绝无容身之地。当她在这样一个 “逻辑社会” 中待久了,就会对不合逻辑的事情、没有客观根据的事情产生极强的抵触情绪

    • “但是,如果转行干别的…… 放眼望去其他的行业我都觉得十分无聊。就好像我做的工作比他们那些普通人都要高端,我比他们都高一个层次。不知不觉之间,我已经变得这么高傲自大、藐视别人了。连我自己都特别厌恶这样的自己……”
    • 因为计算机只能接受 “非黑即白” 这种二元对立型的逻辑,所以和计算机接触的人类的思维模式也会被计算机 “改造”,变得越来越像计算机
  • 在 “职业” 一栏填 “家庭主妇” 的女性,其实也有很多在做各自的副业。比如,利用年轻时在国外居住的经历开个外语班,教小孩子们外语,或者从国外代购一些高级生活用品之类的。

    • MC:现在的副业,斜杠青年好多从事的也是类似工作。原来现在所谓的代购,一点都不新鲜,只不过工具和方式适应了时代发生变化而已。
  • 计算机软件行业从业者每天都在和计算机独处,工作强度很高,日复一日、年复一年。听说在这样的公司里,经常能够听到有人发出野兽一般的吼叫。也许就在他们每天压抑着人类的感情波动、一心只求自己的思维能够和计算机同步的同时,心中也会存留着重做人类的欲望。

  • 我们人类究竟在通过计算机追求什么呢?归根结底,还是‘缩短时间’这一永无止境的任务。我们的工作就是使用各种技术,不断寻找缩短处理问题的时间的方法。

自闭化的社会

  • 在考察 “计算机与人” 的关系的时候,最重要的视角在于这个人是在一个怎样的现实体验中获得人生的成长。

    • 如果心灵的体验十分贫乏、人格不够健全的话,就不会在面对美丽的自然景观时感到喜悦,也不会在看到艺术品后心灵像受到涤荡一样产生清爽的向往。或者说,这种向往已经干涸,只能对工作后的成就感产生快感
  • 技术应激这一发生在软件技术人员身上的典型症状 -- 比如凡事都要用二元对立的思维分出是非黑白,或者因为计算机对人类顺从、忠诚好相处,而厌恶和有感情的人类打交道等心理现象 -- 是由于他们本身就具备容易产生这种症状的人格,才能在计算机的影响下诱发心理上的异变。

  • 计算机会煽动人们的求知欲和好奇心,将逻辑的快乐像 “毒品” 一样注入我们的身体。在 “毒品” 的召唤下,人们和计算机的感情愈发亲密的同时,和他人之间的关系却变得空洞化。

  • 我们人类获得生存价值感有两个条件:一是职业活动中的成就感,另一个是人际关系中获得亲密性带来的满足感。然而现代工业社会却强迫人们仅通过职业活动的成就感去获得人生的满足。极端来说,就是只要有工作,其他什么都无所谓了,根本无暇顾及排解寂寞、充实自己等方面的需求。

  • 家长在养育孩子的时候,太过情绪化地关心孩子、给孩子过高的期待,反而会忽视孩子所需的关爱和心理上的其他需求,让孩子对人类的感情产生抗拒心理,厌恶和他人打交道。

    • 在体验现实的过程中充实自己的心灵。
  • 他们都像是被一层无色透明的胶囊所包裹着,和外界之间隔着一道厚厚的屏障,从不与他人交心 —— 这就是所谓的 “胶囊人类”。
    • 虽然他们表面上可以与人对话,但话题全都是些新出的汽车,或者哪个饭店的法国菜好吃什么的。也就是说,他们说出来的不过是‘信息’而已。
      • 他们认为只要能交换信息、看起来能说得上话,就是所谓的人际关系。但其实,明朗快活只是肤浅的表面现象,他们的关系只停留在高高兴兴地交换信息而已
  • 最近很多父母甚至认为 “最好尽量避免感情的波澜,过平稳、顺利的生活才是幸福的家庭”。越来越多的家庭中,夫妇之间、亲子之间简直就像陌生人一样,所有人都只是表演着幸福的家庭而已。
  • 我们每一个人,就像一个个顺从的精密部件一样,被组装、吸纳进计算机系统里面,逐渐变成机器。对于这点,我们就像患了感觉迟钝症一样,完全没有抗拒。

呕吐的女人

狂乱的独角戏

  • 她看起来不擅长用语言描述自己的感觉,用的也都是些类似 “快感”“轻松的感觉”“幸福的感觉” 这种平淡无奇的词语。交流之中,我看到了她无法与人分享自己感受的遗憾。

    • MC: 无法清楚表达自己的感情和直觉,也是一种缺失和遗憾。
  • 幼儿园老师们的话语中透露出了这样的担忧:将孩子看作一个无法替代的生命,无条件地倾注自己的一切,通过最原始最坦诚的爱,全面接受孩子的一切 —— 这样的家长在如今社会里越来越少了。

    • 有一个老师甚至说,家长们的眼神 “十分冰冷,无时无刻不在将自己的孩子和别的孩子的能力进行比较”。
      • MC: 我们对孩子的爱,开始附加条件,不是纯粹的爱。
  • 因为她的母亲是一个情感比较淡漠,但十分理智的人,所以仅仅停留在从理智上理解孩子,而非用自己的心灵去全面地接受孩子。大概是她做不到这点吧。

  • 母亲作为一名女性,也存在依赖丈夫、希望从丈夫那里得到关爱的心理。然而对于这些需要扮演父亲角色的母亲来说,她们的这种心理需求非但得不到满足,反而要压抑自己对于关爱的需求,一个人面对生活中的一切。而只有她们在夫妻关系中获得满足,有一个稳定的内心世界,才能对自己的孩子倾注充分的母爱……

  • 孩子和双亲之一关系过度亲密,形成了 “模拟夫妇” 的关系,而另一方家庭成员却始终缺席。这种关系不仅限于母女,也有父女形成 “模拟夫妇” 的情况。

  • 对于从刚出生到三岁的婴儿来说,母亲是一个能够接受、包容一切的依存对象。而等孩子成长到需要规范行为的教育阶段,母亲就会禁止某些行为,变成一个只能包容部分的依存对象。通过这个过程,能够包容自己的母亲和不能包容自己的母亲合二为一,成为一个完整的母亲形象。但是,如果一开始没有一个能够彻底依存的对象,孩子就会不停地寻求这样一个缺失的对象……

  • 心理专家们对这一现象的看法其实并不统一,而且他们都默契地表示自己的解释 “仅仅是假设”,回避确定性的回答。在这种情况下我的选择只有一个,就是尽可能多倾听各方面的意见。

  • 没有影子的、半透明的生物一样的女人们,一个接一个地出现在深深的海底,飘摇在蓝白色的光亮之中,随后消失。

  • 这一切都是她不断勉强自己、通过挑战极限状态才得来的结果。而她对自己的要求又高得离谱,不愿接受未达标的自己。如果这时她能够承认自己的失败,退出这个死循环,就能获得解脱,但她又不甘心认输,才会把自己弄成一副皮包骨头的病态模样,让别人以为她是因为身患疾病才没有成就更高的发展

  • 很多像她这样的患者都接受不了原原本本的自己,而是希望通过控制和加工自己获得社会认同。然而她们这样做并非仅仅想获得社会的好评,而是在苦苦寻求一个能够原原本本接受自己的存在。

    • 一般人都会量体裁衣,而她却反过来削足适履,不断按照社会上的价值观来改造自己、强迫自己,自我肯定的意识非常淡薄。
  • 学历、地位、财产 -- 那些一切都以超一流为目标不断拼搏,又对社会顶层心存强烈执念的人们,双眼总被这一目标蒙蔽,到最后心中只剩下无限的空虚

为妻为女

  • 海岬像一双温柔的臂膀,从两侧环抱着这个小小的海湾。岸边绿、红、黄、白的房屋,就像鲜花一样点缀着海湾。

  • 回国之后,有一天他忽然向我求婚…… 还说不久之后,可能会被公司派去国外工作,让我跟他一起出国,去国外的大学读研究生,所以要赶紧把英语学好…… 那时候我也觉得可以跟他组建一个温暖的家庭,之后要是能跟他一起去美国留学就更好了。心中对未来充满了憧憬……

两个自己

  • 虽然女人们都认为自己想要瘦下来是出于自己的审美,但实际上,我认为这是她们已经彻底被男性占主导地位的社会价值观所吞噬、所洗脑的结果。

  • 人类有控制他人的欲望。有人通过依赖去控制他人,也有人如果不被人依赖就会心神不宁、坐立难安。所谓依赖共生关系,就是指这两者之间所构成的依赖和被依赖的关系,或者说是统治与被统治的关系。

    • 在依赖共生的同时,为了填补无法完全控制对方时所产生的寂寞、愤怒、渴望等负面感情,就会产生对食物、酒精、药物的依赖,进而染指赌博、滥交、浪费等行为。
    • 所谓依赖共生关系,是指一个通过让对方依赖自己而控制对方的人,和一个通过依赖对方来控制对方的人之间所形成的依赖与被依赖的人际关系成瘾。形成这种关系的两个人会无止境地向对方索取,通常会形成互相憎恶却无法分开、互相蔑视却不能缺少对方的局面,重复着爱恨纠缠的悲剧。
  • 江津子和上班族的丈夫两人住在这样一个 “人工” 的小镇。虽然已经结婚三年,但大概是因为还没有小孩,这个年轻的主妇脸上还留着些许学生气

  • 我们人类,每一个人都是一个无法替代的生命,都是一个不可以通过容貌、能力、地位来排序的、独一无二的宝贵存在。或许我们可以将其称为 “人类观”,一种发自内心的尊崇个性、尊敬并爱护人类的价值观。

后记

  • 现在这个词的意义,就只剩下被人们忘却的无色无味、不痛不痒的每一天,像一座无人的工厂一样在那里毫无意义地空转而已。

  • 日本人工作到死的过程,不仅是为了 “垃圾” 而工作的过程,同时也是通过大量生产、大量消费垃圾,来维持饱食繁荣的现状的过程。

  • 通过将容器改成铝制,销售方式也从人卖给人变成了自动售货机贩卖。自动售货机的生产量飞速增长,以至于现在存量已超二百五十万台,可以说是遍布全国。

  • 为了维持生产和消费的节奏我们拼命地工作,同时大量进口制造垃圾的能源 -- 石油。

  • 我们真的可以乘坐着这样一艘被充满欺瞒的 “垃圾” 和泡沫托着的破船,漫无目的地航行在茫茫大海上吗?

追踪采访 寂寥的穷民们漂泊依旧

  • 现代市民受到暴力压迫的情况少了很多,然而,严格的评价制度取代了暴力对人进行管理,并依据人的 “质量” 进行阶层划分。社会的评价制度在内化后形成了人们的自我评价,使人们自觉主动地将自己客体化,并努力成为对他者(社会)来说的 “优质产品”。

    • MC:作者的文笔和思考准确,描述出了当下社会的一个现实截面。
  • 所有人都在希求一个没有评价和监视、情绪和身体能不受到伤害的安全地带。然而,学校不是这样的地方,家庭也不是,那人们的安全地带究竟在哪里呢?只要人们不安的根源不消除,这种病症就不会根除,只会继续增加。

    • 对于男性来说,公司是一个像母体一样的地方。公司就像是他们的母亲。再反观女性,不光无时无刻都活在来自男性的评价之中,就连与生俱来无法改变的长相都要被人残酷地挑剔。所以,就算她们想通过拒食和过食寻求短暂的退化,也是完全可以理解的。
  • 她们的父亲过度适应公司的工作,沉湎于提高效率、增加利润的行为,除了工作以外对其他事物全无任何兴趣,可以说是脑子里被灌输了工作程序的 “机器人” 职员。她们的母亲为这样的丈夫奉献一切,只能在对孩子的过度关怀中寻求自己的价值,也是脑子里被灌输了如此价值观的贤妻良母 “机器人”。这些女性都是在这样一对对依赖共生关系下的 “机器人” 家庭里长大,按照事先安排好的剧本走进良好的学校,成为贤妻良母,被驱赶着走上设计好的、没有坎坷的人生,然而她们一定看破了其中虚伪的本质。也没关系嘛…… 现在的社会连人们的愤怒都能吸收,让其烟消云散。人们迷失了自己真正的需要。现在对日本职业足球联赛的狂热给人一种很是虚伪的感觉,就像是人为炒起来的一样。我们就是这样被看不见的暴力驯服成一群忘记愤怒、没有力气的优良市民

    • 就像是温柔版的法西斯主义?对对,就是这种。也就是说社会整体都变得像‘机器人’一样。
  • 最近最让人忧心的,是无法接受自己的人越来越多。她们不单单是对于学习之类的事情缺乏自信,而且严重缺乏让别人接受、认同自己的存在的体验。由于缺乏和他人建立亲密关系的经验,她们对现状严重不安。所以,哪怕是一点点挫折都会让她们坠入孤独的深渊,产生被人抛弃的感受

  • 爱情和亲密关系,本不应该是必须达成目标后才能获得的东西,不能像解决其他问题一样,先设定一个目标,然后思考方法、制订计划后才能获得爱。然而让我们看看现在的亲子关系,家长的爱不再是无私的、无条件的给予和接受,而是必须达成某些目标之后,才能得到,才有资格成为所谓的 “乖孩子”

  • 比如夫妻之间本应该可以推心置腹地进行交流,但现实中真正能做到的夫妻却并不多。虽然表面上看上去十分和睦,但内心却并不能充分交流。这种关系被称作伪交互性,在这种关系下,夫妻双方都认为一旦发生矛盾就会分手,所以会想办法相互迁就。这种状态让人不禁觉得,他们之间的关系是缺乏感情的波澜和迸发,是稀薄且充满虚伪的,就像在表演自己的角色一样…… 就连关爱、照顾他人都被当作任务来完成,可以说是一种虚伪的关系

  • 我觉得,越是能够容许孩子们绕弯、跌倒的社会,就越能保留孩子们的天性,这个社会、集团中个体的生存能力就越顽强。然而现在的社会能够容忍孩子绕弯的幅度越来越小,认为这个容忍幅度一旦超出某个程度,就再也回不到正轨

    • 现在的孩子们从小就在自己的心里放了一个小口袋,将本真的自己收进这个口袋里。
  • 她的这种病症,属于儿童抽动症中的‘抽动秽语综合征’,越是不可以说的话就越要说,越是在不可以说的地方发病就越严重。这个病症,就像是对不允许出格的社会的反照、讽刺和抗争一样。

  • 其实,无论是拒食的孩子还是过食的孩子,好多人都对我说不想把病治好,想就这样保持病态。他们周围的人,要么在催促他们治疗,要么鼓励他们不能因此丧失自信,只要努力就会有希望等。对于病人来说,这是最不愿意听到的话语。他们根本不想治疗,也不想抱希望,因为对于他们来说,明天、未来不知道会比现在更加悲惨多少。对他们来说,处于病态反而意味着他们的生命是有所保障的。

  • 在现代社会,不这样做的话家庭就无法适应社会,所以家长们才会不惜一切去执行。然而,他们越是想去适应社会,孩子们受到的压迫就越是厉害。

    • MC:内卷,适者生存,如果你不这样做,那么你就无法生存下去,被迫参与社会的竞争。
  • 无法表露真实的自己,被迫戴上面具伪装出另一个样子生活下去,由此造成的痛苦才是万病之源。孩子只有沿着家长给他规划好的路线、言听计从才能成为优等生。虽然他们可能会被人推举当个班长、学生会主席之类的,但作为一个人来说可能会被孤立。而对于孩子自身来说,到了一定年龄后,当在外部的体验中碰壁,就会将目光转向自己。

  • 这个过程被称为家庭的重组,家长和孩子的价值观都会产生变化。只要家庭成员能够达成共识,认为别人的眼光其实无所谓,社会上的价值观也不那么重要,就能迎来希望的曙光

  • 孩子们本来需要无穷无尽的、无条件的爱,如果对爱的需求无法获得满足,产生了依赖性的性格,就会寻找其他事物去代替其所需的爱,并以此填补心中对爱的需求。

  • 然而今天,现代社会(西欧社会)的自我理想终于开始变得破绽百出。对于自身力量的信仰将胜者变为 “努力成功” 的俘虏,将败者变为寂寞和渴望的奴隶。在寂寞和渴望中产生了对酒精、药物、食物、性、赌博、购物的依赖症状。

  • 我们究竟想要做什么?想要度过怎样的人生?在我们尚未思考出结论时,我们自身中机械性的部分就已经擅自启动,和全家人一起按照 “幸福家庭” 的剧本表演着过家家一样的生活 —— 这是一群追求和他人一致外表、和他人同等稳定的 “趋同成瘾机器人”。隐藏在饱食泡沫时代背后的,就是这样一群时代囚徒颠沛流离的景象

  • 作者在本书的 “追踪采访” 章节的末尾处向每个读者抛出了一个值得深思的问题。“我们究竟想要做什么?想要度过怎样的人生?” 书中的一个个事例看似纷杂,但其实都贯穿着同样的设问。

译后记

  • 虽然本书在国内出版距原作在日本上市有近二十五年的时间差,书中所述的不少事情也已经过去了三十多年甚至更久,但读过本书的读者一定会发现,如今发生在我们身边的一些社会现象和书中所述存在惊人的相似之处。比如,日本当年盘踞在车站前的小微贷,如今早已将阵地转移到了手机和互联网上。日本当年红极一时的自我启发活动,如今也包装成精美的个人提升、企业培训课程粉墨登场,令许多企业管理层与普通白领趋之若鹜,不惜花高价去学习;从近来引发社会广泛关注的 “996 工作制” 中,译者也仿佛看到了很多日本上班族日夜拼命工作的身影

  • 日本社会曾经历过的事情,如今有一些或原原本本,或改头换面,或多或少发生在我们自己的身上。

  • 对于我们来说,这本写于三十多年前的纪实文学不应是 “隔岸观火”“事不关己”,而应是一面照出我们自己得与失的 “明镜”,值得我们更好借鉴。


我的随想

在现在这个浮躁的社会,我们刚刚经历了房价暴涨,经济前景不明,不禁思考未来社会会何去何从?

幸好隔壁邻居先中国 30 年经历了经济高速增长时期,所以我一直想读一本书,窥视 80 年代末经济停滞前的日本最后的狂欢,来为现在的自己提个醒,帮助自己更好地对未来做一些预测。

这是我第一次读相关的书,当我捧起这本书时,看到了一个个熟悉的社会百态,比如小额借贷,买房,加班过劳死,35 岁退休等等,只不过工具和形式为了适应时代做出来调整和更改。

如果你赞同中国未来的发展可能会和日本类似,那么这本书就像一个长着告诉你各种可能发展以及未来的状态。你可以在比较中选择适合自己的发展方式,对我而言,可能更偏向于适度工作,追求体验,享受和家人朋友在一起的时光,让生活充实有趣

作为刚毕业不久的打工人,在没有读书前,我是一个满心斗志的加班人,希望在职场做出一番事业来。这本书让我逐渐意识到,日本在 80 年代就已经开始了 996 的加班生活,自己正在被社会评价指标裹挟着成为一个工具人,除了工作对其他事情都不感兴趣,我的未来是何其枯燥和无聊。我要有最后的倔强,我希望自己能够多去亲近大自然,扩宽自己的视野,最末和朋友聚一聚

我是一名程序员,也经常会被电脑吸引着坐在屏幕前几小时,看到事物的思维开始二值化,不愿意去处理复杂的人际交往关系,这可能是程序员的共性。这本书告诉自己,程序是有意思的工作,但是要谨防上瘾,自己需要不断地反思,锻炼自己的思维能力,从更高的视野看待事情。

不可否认,中国现在已经步入低增长时期,国家和社会在积极地扩展内需,我们受到的诱惑只增不减,总是会有一个声音告诉你,你需要什么,甚至你连思考都没有就开始购物。在社会开始疯狂的时候,自己需要坚持不持有的生活,理性看待不必要的消费,不要跟随大流去疯狂购物。

这本书给了自己一些新奇的观点:

  • 我和同事的交流,只限于信息交流,没有深刻的内心沟通;
  • 如果不能准确地表达自己的感受,那么是一种自己的缺陷和遗憾;
  • 人生苦短,不要参与进来内卷的过程,你需要花费更多的时间来体验时间,丰富心灵,而不是被社会裹挟着向前盲目走。

[toc]

std

std::numeric_limits

  • The std::numeric_limits class template provides a standardized way to query various properties of arithmetic types.
    • int 的最大值是 numeric_limits::max().
  • minlowest 都被用来获取某个类型的最小值。它们分别返回这个最小值可表示的最小正数 (min) 和最小负数 (lowest)。因此,当 T 是一个无符号类型的时候,min () 和 lowest () 返回的值是相同的。其次,lowest () 只对有符号类型有效,而 min () 对所有数据类型都有效。
++view raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <limits>

int main(){
int max_int = std::numeric_limits<int>::max();
int min_int = std::numeric_limits<int>::min();
int lowest_int = std::numeric_limits<int>::lowest();
std::cout << "max int is " << max_int << std::endl;
std::cout << "min int is " << min_int << std::endl;
std::cout << "lowest int is " << lowest_int << std::endl;

// output is
// max int is 2147483647
// min int is -2147483648
// lowest int is -2147483648

return 0;
}

std::sort

  • Sorts the elements in the range [first, last) in non-descending order.
    • 要求传入两个迭代器确定范围
  • 逆序排序 std::sort (vec.rbegin (), vec.rend ())

std::equal

  • Two ranges are considered equal if they have the same number of elements and, for every iterator i in the range [first1, last1), i equals (first2 + (i - first1)).
    • 要求按位置一致
  • std::equal should not be used to compare the ranges formed by the iterators from std::unordered_set/map

Programming grammar

string

std::string::substr

  • Returns a newly constructed string object with its value initialized to a copy of a substring of this object.
  • string::substr (pos, n) 返回从 pos 开始的 n 个字符的拷贝.

std::string::size

  • Returns the length of the string, in terms of bytes.
  • Returns size_t, an unsigned integral type.
    • 不能直接 min (size_t, int), 编译错误

std::string::operator[]

  • Returns a reference to the character at position pos in the string.

stack

std::stack::top

  • Returns a reference to the top element in the stack.
  • 如果栈为空,返回值未定义。

map

std::map::insert

  • 插入元素类型是 pair, 可以是 insert ({key_x, value_y}), 或者是 insert (make_pair (key_x, value_y)).

const int * vs const int * const vs int const *

  • int const* is equivalent to const int* 指向常量 int 的指针 > This means that the variable being declared is a pointer, pointing to a constant integer. Effectively, this implies that the pointer is pointing to a value that should not be changed. Const qualifier doesn’t affect the pointer in this scenario so the pointer is allowed to point to some other address.

  • int *const 指向 int 的常量指针 > This means that the variable being declared is a constant pointer pointing to an integer. Effectively, this implies that the pointer shouldn’t point to some other address. Const qualifier doesn’t affect the value of integer in this scenario so the value being stored in the address is allowed to change.

  • const int* const is equivalent to int const* const 指向常量 int 的常量指针 > This means that the variable being declared is a constant pointer pointing to a constant integer. Effectively, this implies that a constant pointer is pointing to a constant value. Hence, neither the pointer should point to a new address nor the value being pointed to should be changed.

  • Memory Map

One way to remember the syntax (according to Bjarne Stroustrup) is the spiral rule - The rule says, start from the name of the variable and move clockwise to the next pointer or type. Repeat until expression ends.

Using this rule, even complex declarations can be decoded like, int ** const is a const pointer to pointer to an int.

以 * 为界, 在 * 前后的 const 可以和同侧的 data type 调换位置,不影响变量表达的含义。

std::numeric_limits::min() vs lowest()

根据 ppreference 定义:

  • lowest: Returns the lowest finite value representable by the numeric type T, that is, a finite value x such that there is no other finite value y where y < x.
  • min:For floating-point types with denormalization, min returns the minimum positive normalized value.

也就是说,

  1. 如果 T 属于 int 型,則 min 和 lowest 会返回一样的值,皆为该类型的最小值(负数或 0)。
  2. 如果 T 属于浮点型,min 返回 "最小正数",lowest 返回最小值。

std::move 对象移动

在重新分配内存的过程中,从旧内存将元素拷贝到新内存是不必要的,最好的方式是移动元素;此外,IO 类和 unique_ptr 类可以移动但不能拷贝。

  • 标准库容器、string 和 shared_ptr 类既支持移动也支持拷贝。IO 类和 unique_ptr 类可以移动但不能拷贝。

变量是左值,我们不能将一个右值引用直接绑定到一个变量上,即使这个变量是右值引用类型也不行。

针对上述问题,我们可以使用 move 的新标准库函数显式地将一个左值转换为对应的右值引用类型,来获得绑定到左值上的右值引用。

1
2
3
4
5
int &&rr1 = 42;  // 正确:字面常量是右值
int &&rr2 = rr1; // 错误:表达式rr1是左值。
int &&rr3 = std::move(rr1); // 正确。

调用move意味着承诺:除了rr1赋值或者销毁它外,我们将不再使用它。我们不能对移后源对象的值做任何假设。

我们可以销毁一个移后源对象,也可以赋予它新值,但不能使用一个移后源对象的值。

  • 与多数标准库名字的使用不同,对 move 我们不提供 using 声明,我们直接调用 std::move 而不是 move。

std::set

STL 中 set 底层实现方式?

  • set 底层实现方式为 RB 树(即红黑树)。
  • 红黑树与 hash table 最大的不同是,红黑树是有序结构,而 hash table 不是。
    • 如果只是判断 set 中的元素是否存在,那么 hash 显然更合适,因为 set 的访问操作时间复杂度是 log (N) 的,而使用 hash 底层实现的 hash_set 是近似 O (1) 的。
    • set 应该更加被强调理解为 “集合”,而集合所涉及的操作并、交、差等,即 STL 提供的如交集 set_intersection ()、并集 set_union ()、差集 set_difference () 和对称差集 set_symmetric_difference (),都需要进行大量的比较工作,那么使用底层是有序结构的红黑树就十分恰当了,这也是其相对 hash 结构的优势所在。
  • 在 STL 中,set 和 multiset 都是基于红黑树实现的。

什么时候使用 std::move

When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.

To answer the question in the title, use std::move on a return value when you want it to be moved and it would not get moved anyway. That is: - you want it to be moved, and - it is an lvalue, and - it is not eligible for copy elision, and - it is not the name of a by-value function parameter.

Reference to When should std::move be used on a function return value? [duplicate].

at vs operator[] in vector

at returns a reference to the element at position n in the vector, which automatically checks whether n is within the bounds of valid elements in the vector, throwing an out_of_range exception if it is not.

operator[] returns a reference to the element at position n in the vector container. Portable programs should never call this function with an argument n that is out of range, since this causes undefined behavior.

operator[] has the same behavior as at, except that vector::at is bound-checked and signals if the requested position is out of range by throwing an out_of_range exception.

在程序中推荐使用 at 函数,而不是 [] 操作符,更安全。

explicit 抑制构造函数定义的隐式转换

关键字 explicit 只对一个实参的构造函数有效。只能在类内声明构造函数时使用 explicit 关键字,在类外部定义时不应重复。 当我们用 explicit 关键字声明构造函数时,它将只能以直接初始化的形式使用。而且,编译器将不会在自动转换过程中使用该构造函数。

需要多个实参的构造函数不能用于隐式转换,所以无需将这些构造函数指定为 explicit 的。实测,即使指定为 explicit,程序编译不报错。

std::upper_bound vs std::lower_bound()

upper_bound

std:vector 和 std:string 的相互转换

  • string::assign
    • Assigns a new value to the string, replacing its current contents.
  • vector::assign
    • Assigns new contents to the vector, replacing its current contents, and modifying its size accordingly.
  • vector to string
    1
    2
    3
    4
    // First method
    std::vector<char> data = {'a', 'b', 'c'};
    std::string res;
    res.insert(res.begin(), data.begin(), data.end());
1
2
3
4
5
// Second method
std::vector<char> data = {'a', 'b', 'c'};
std::string str;
str.clear();
str.assign(data.begin(),data.end());
  • string to vector
1
2
3
4
string str = "what a nice day!";
std::vector <char> chars;
chars.resize(str.size());
chars.assign(str.begin(),str.end())

函数模板 (function template) 返回值

https://blog.csdn.net/u012515223/article/details/17003679

boost::optional()

  • 读取访问器 (read access) .get () 返回非常量引用 (non-const reference),所以你可以向其中写入。

It is sometimes helpful to think of optional as a value-and-pointer mixed together. There is a possibly null pointer to an owned buffer of memory that may, or may not hold a copy of the type.

你可以使用 * 或者 -> 来替代 get () 函数,以下三种写法是等价的。

1
2
3
*optional
optional->
optional.get()

Grammar Discriminate

构造函数初始化 (赋值和初始化)

我们一般习惯于构造函数初始化列表函数体内对类的成员变量初始化,两者的区别难道仅仅是表达方式和初始化位置不同吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 辨析两种初始化参数的方式 

// Just show me the code!
// 构造函数初始化列表 (constructor initialize list)
ClassA::ClassA(const std::string& name_in):name_(name_in) {
// 只调用了默认构造函数,不会再调用拷贝构造函数。
}

// 赋值初始化
ClassA::ClassA(const std::string& name_in) {
// 对象的成员变量的初始化动作发生在进入构造函数体之前。
// name_不是初始化而是赋值。首先调用了这个类的默认构造函数,然后将name_in赋值到name_,即在调用拷贝构造函数。
name_ = name_in;
}

C++ 规定,当某个数据成员被构造函数初始化列表忽略时,它将以与合成默认构造函数相同的方式隐式初始化。即没有出现在构造函数初始化列表中的成员将通过相应的类内初始化(如果存在的话)初始化,或者执行默认初始化。

综上所述,相比函数体内初始化,使用成员初始化列表,程序的效率更高。

动态绑定

  • 当我们使用基类的引用或指针调用一个虚成员函数时,会执行动态绑定。所以,所有的虚函数都必须有定义。
  • 动态绑定只有当我们通过指针或引用调用虚函数时才会发生。因为当某个虚函数通过指针或引用调用时,编译器产生的代码直到运行时才能确定应该调用哪个版本的函数。

默认构造函数

  • 一旦我们定义了一些其他的构造函数,那么除非我们再定义一个默认的构造函数,否则类将没有默认构造函数。
  • = default : 声明默认构造函数,等同于之前使用的合成默认构造函数。

Vector

  • 当 vector 对象(或数组)销毁时,存储在其中的对象也会被销毁,也就是依次销毁 vector 中的每一个元素。
  • 很多使用动态内存的类应该使用 vector 对象或者 string 对象管理必要的存储空间;使用 vector 或者 string 的类能避免分配和释放内存带来的复杂性。

inline

  • 引入原因: 为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了 inline 修饰符,表示为内联函数。栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间。
  • inline 只适合涵数体内代码简单的涵数使用,不能包含复杂的结构控制语句,并且不能内联函数本身不能是直接递归函数(即,自己内部还调用自己的函数).
  • inline 函数仅仅是一个对编译器的建议,所以最后能否真正内联,由编译器决定。一个好的编译器将会根据函数的定义体,自动地取消不值得的内联
  • 定义在类中的成员函数默认都是内联的,如果在类定义时就在类内给出函数定义,那当然最好。如果在类中未给出成员函数定义,而又想内联该函数的话,那在类外要加上 inline,否则就认为不是内联的。
  • 内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。
    • 如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。
  • inline 不应该出现在函数的声明中,原因如下:
    • 高质量 C++/C 程序设计风格的一个基本原则:声明与定义不可混为一谈,用户没有必要、也不应该知道函数是否需要内联。
    • 一个好的编译器将会根据函数的定义体,自动地取消不值得的内联(这进一步说明了 inline 不应该出现在函数的声明中)。
1
2
3
4
5
6
7
8
9
10
// 头文件
class A
{
public:
void Foo(int x, int y);
}

// 定义文件
// 关键字 inline 必须与函数定义体放在一起才能使函数成为内联,仅将 inline 放在函数声明前面不起任何作用。
inline void A::Foo(int x, int y){}

Copy Constructor 拷贝构造函数

一个特殊的构造函数,一般只有一个参数,这个参数一般是用 const 修饰的,对自己类的一个引用 (reference)。

浅拷贝和深拷贝

浅拷贝:两个变量进行浅拷贝时,它们指向同一个地址,它们的值相同。这样会有问题,当其中的一个析构了那个地址,另外一个也没有了,有时候会发生错误,但浅拷贝比较廉价。

深拷贝:两个变量进行深拷贝时,第二变量会重新申请一块区域来存放跟第一个变量指向地址的值。两个东西完全是独立的,只是值相同。消耗比较大,因为要重新申请空间。

Code Style

class

1
2
3
// Setter

// Accessors

Friends

Initialization: =, (), and

  • For uniform initialization syntax,大括号初始化 (Brace Initialization) 的潜在问题:
    • “uniform” is a stretch: there are cases where ambiguity still exists.
    • This syntax is not exactly intuitive: no other common language uses something like it.
      • For uniform initialization syntax, we don’t believe in general that the benefits outweigh the drawbacks.

Best Practices for Initialization

  • Use assignment syntax when initializing directly with the intended literal value (for example: int, float, or std::string values), with smart pointers such as std::shared_ptr, std::unique_ptr, with containers (std::vector, std::map, etc), when performing struct initialization, or doing copy construction.
  • Use the traditional constructor syntax (with parentheses) when the initialization is performing some active logic, rather than simply composing values together.
  • Use {} initialization without the = only if the above options don’t compile.
  • Never mix {}s and auto.
    • For the language lawyers: prefer copy-initialization over direct-initialization when available, and use parentheses over curly braces when resorting to direct-initialization.

[toc]

Commands

  • 命令行终端输入: vimtutor。 这是史上最简单、最全面的 vim 基础教程,至今无人超越。
  • tree
    tree 命令用于以树状图列出目录的内容,它会列出指定目录下的所有文件,包括子目录里的文件。

功能扩展

文本整体的处理

  • gu:切换为小写
  • gU:切换为大写
  • ~:切换光标所在位置的字符的大小写形式,大写转换为小写,小写转换为大写。
  • 3~:将光标位置开始的 3 个字母改变其大小写

如何删除一个单词

  • dw
    • 从光标当前的位置开始删除,直到单词最后。
  • daw
    • 删除光标所在的单词,简记 delete a word。
  • bdw
    • 复合命令,b 可以让光标回退到单词开头的位置,而 dw 则是从头开始删除单词。
1
2
3
# de 删除至当前单词末尾,包括当前字符
# d$ 删除至当前行尾
# 2dd 删除两行

移动光标

1
2
3
4
5
6
# hjkl
# 2w 向前移动两个单词
# 3e 向前移动到第 3 个单词的末尾
# 0 移动到行首
# <ctrl>+o 跳转回之前的位置
# <ctrl>+i 返回跳转之前的位置

修改

1
# A 当前行末尾添加

撤销

1
2
# u 撤销
# <ctrl>+r 取消撤销

状态

1
# <ctrl>+g 显示当前行以及文件信息

查找

1
2
3
4
5
6
# / 正向查找(n:继续查找,N:相反方向继续查找)
# ? 逆向查找
# :set ic 忽略大小写
# :set noic 取消忽略大小写
# :set hls 匹配项高亮显示
# :set is 显示部分匹配

替换

1
2
3
# :s/old/new 替换该行第一个匹配串
# :s/old/new/g 替换全行的匹配串
# :%s/old/new/g 替换整个文件的匹配串

搜索

  • 匹配末尾
1
/关键字\>
  • 匹配开头
1
/\<关键字
  • 排序
1
!sort

复制到剪贴板

  1. 查看 vim 版本是否支持 clipboard
    1
    vim --version | grep "clipboard"
  2. clipboard 前面如果有一个减号,说明不支持,需要 安装图形化界面的 vim。
    1
    sudo apt-get install vim-gnome
  3. 打开 vim 输入 :reg 查看 vim 的寄存器,当支持 clipboard 之后,会多出 "+ 寄存器,表示系统剪切板。在 vim 中进入 visual 视图后,使用 "Ny (N 表示特定寄存器编号),可以将内容复制到特定的剪切板,那么我们的目的是要复制到系统剪切板则需要选中内容后输入命令:
    1
    "+y
  4. 同理,"+p 将系统剪切板的内容拷贝到 vim 中(非编辑模式下)。
    1
    "+p

多窗口调整窗口大小

1
2
3
4
5
6
7
8
9
// 命令行模式下 
// 纵向调整 []输入可选,可以输入也可以不输入,num 指代一个数字
:res[ize] num // 指定当前窗口为num列num行
:res[ize] +num // 把当前窗口高度增加num行
:res[ize] -num // 把当前窗口高度减少num行
// 横向调整
:vert[ical] res[ize] num // 指定当前窗口为num列
:vert[ical] res[ize] +num // 把当前窗口增加num列
:vert[ical] res[ize] -num // 把当前窗口减少num列

参考链接

显示行号

命令行模式,输入 “set number” 或者 “set nu”。

替换文本

  • 对于替换命令 s 来说,如果要替换掉换行符,需使用 作为搜索串;如果要替换字符串生成新行,请使用 为目标串。

References

[toc]

Online Tools

Online IDE

  • cpp.sh
  • 在线 IDE - repl.it
    • 一个完美的在线 IDE,你可以在几秒钟之内为你喜欢的编程语言或技术栈启动一个编程环境。它支持所有现代编程语言,比如 Python、Kotlin、Ruby 和 JavaScript。你可以安装语言库和包,然后直接使用它们,免去下载和管理工作。
    • 你也可以直接通过 repl.it 链接分享代码,还能通过嵌入 repl.it 链接让用户与代码交互。

Online Resource

  • ZLibrary
    • The world's largest ebook library.
    • ZLibrary 是一个免费电子书籍搜索下载网站,成立于 2009 年,目前收录超过 500 万本电子书籍,主要是英文原版的电子书籍,读者可以根据关键词来搜索,也可以通过 ISBN 码搜索,另外也提供了下载历史记录方便查看历史记录。
  • 达牛的博客
    • 达牛对日常办公使用频率较高的工具做了一些收藏整理,基本都是破解版软件。
    • visio 2019 激活方法

English Writing Polish

Translation

  • Google Translate
    • 谷歌翻译在通过采用谷歌神经机器翻译 (GNMT:Google Neural Machine Translation) 系统后,可以极大提升翻译效率,在科技文、商务文方面尤为出色,但在文学、艺术领域还有待提高。
  • Bing Translator
  • Urban Dictionary
    • 欧美青少年用语;年轻人口头禅、俚语
  • Online Slang Dictionary
    • 英美习语大全
  • Trados
    • Trados 是本地化工作者必不可少的工具,它能提升翻译内容的一致性,减少重复劳动,降低翻译项目成本。
  • COCA 语料库
    • 语料库是指经科学取样和加工的大规模电子文本库。适用于英语深度学习者、学者、研究人士。

Programming Resources

地图工具

  • 全球船舶 AIS 信息
    • 船舶自动识别系统 (Automatic Identification System, 简称 AIS) 是一种新型的助航设备。AIS 基本功能是:将本船和他船的精确船位、航向、航速(矢量线)、转向速度和最近船舶会遇距离等动态信息和船名、呼号、船型、船长与船宽等静态信息通过 VHF 自动、定时播发,在 VHF 覆盖范围内(20 海里)装备 AIS 设备的船舶,可自动接收到这些信息。
  • 百度地图坐标拾取系统

pip 是什么

pip 是一个通用的 Python 包管理工具,提供了对第三方 Python 包的查找、下载、安装、卸载的功能。

注意:不是所有的第三方 Python 包都能通过 pip 来安装,只能是发布在 pypi.org 上面的才能通过 pip 安装。

pip3 和 pip 的区别

如果机器同时装有 python2 和 python3,那么 pip 默认给 python2 用,pip3 指定给 python3 用,两者的安装路径是不同的。

如果机器只有 python3,pip 和 pip3 的作用是一样的。

常用命令

pip 命令帮助

1
pip help

检查 pip 是否安装和 pip 的版本号

1
pip --version

pip 安装第三方包

1
pip install SomePackage

安装该软件的最新版本,同时 pip 会计算该软件的依赖包,如果没有冲突,就会把该软件包的依赖包一起安装。

  • 如果要安装指定版本的软件包呢,就需要在软件包名后面加一个具体的版本号,比如
1
pip install SomePackage==2.21.0

pip 升级软件包

1
pip install --upgrade SomePackage

pip 搜索软件包

1
pip search SomePackage

pip 卸载软件包

1
pip uninstall SomePackage

注意:卸载软件包之前最好先用 pip show 命令看一下该软件包的被依赖关系,如果其它包依赖你要卸载的软件包,那么你卸载后,其它软件包就没法运行了。

pip 查看包信息

1
pip show SomePackage

查看该软件包的作者,软件安装路径,依赖的库和被依赖的库等。

显示本地软件包

1
pip list

list 命令显示本地所有安装的第三方库和相应的版本号。

导出本地所有软件包名和版本号

1
pip freeze > requirements.txt

上面命令会把软件包名和版本号导到 requirements.txt 文件里,方便在另一台电脑上部署一个相同的 Python 软件包环境,或者提交到生产环境去运行,或者一键卸载 / 升级全部的第三方软件包。

  • pip list 和 pip freeze 的区别

pip list 和 pip freeze 的区别是 pip list 列出了所有的包,pip freeze 只列出由 pip 安装的软件包。

升级包到当前最新的版本

1
pip install -U SomePackage

升级 pip

1
python -m pip install --upgrade pip

其他

  • Python 的包管理工具也不只有 pip,还有 Conda、Pipenv、Poetry 等。Conda、Pipenv 的好处是不只能管理包工具,还能管理虚拟路径,让你一台电脑能安装和运行多个版本的 Python,不会发生冲突。

[toc]

git 原理图

git command

git 命令大集合

git add

1
git add -h

查看更详细的帮助内容

1
git add . 

不加参数默认为将修改操作的文件和未跟踪新添加的文件添加到 git 系统的暂存区,注意不包括删除文件。

1
git add -u .

-u == --update,表示将已跟踪文件中的修改和删除的文件添加到暂存区,注意不包括新增加的文件。

1
git add -A .

-A == --all,表示将所有的已跟踪的文件的修改与删除和新增的未跟踪的文件都添加到暂存区。

stash local changes

  • If you want remove all local changes from your working copy, simply stash them.

    1
    git stash save --keep-index  

  • If you don't need them anymore, you now can drop that stash.

    1
    git stash drop

git pull

1
git pull origin target_branch_name

下载指定分支代码合并到当前分支:相当于指定分支的代码与当前分支的代码合并到了一起)。

每次使用该命令前,需要保证本地工作区是没有任何修改代码的,也就是说需要将本地工作区编辑过的文件添加到暂存区 (git add .),或提交到本地仓库中 (git commit),才可以使用该命令拉取指定分支的代码合并到当前分支中。

建议:每次在操作完 git commit 命令后,必须拉取一下 master 分支代码,保持本地正在开发功能逻辑的代码分支代码是最新的,避免后续在提交时冲突过多或覆盖掉其他人的代码的问题出现。

git brach

1
git branch -a

加上 - a 参数可以查看远程分支,远程分支会用红色表示出来

1
git log --graph

查看分支合并图

git log

1
git log --oneline --author=git_name

git log 中根据 author 过滤

1
git log --pretty=one

显示 git 提交记录的第一行,方便检索和管理提交记录

1
git log --oneline --after="2020-05-21 00:00:00"  | grep "region"

查询某段时间的提交记录关键字

git cherry-pick

1
2
3
4
5
nothing to commit, working directory clean
The previous cherry-pick is now empty, possibly due to conflict resolution.
If you wish to commit it anyway, use:

git commit –allow-empty

It’s exactly what it says: the changes you’re trying to cherry-pick are already wholly already integrated/cherry-picked in the branch you’re on. I.e. the result of the cherry-pick is no changes. You can create an empty commit with the --allow-empty flag to indicate that you attempted to cherry-pick, but there were no changes to pull in.

git shortlog

查找 commit description 包含某些字符的 log 日志

1
2
3
4
5
git shortlog --format='%H|%cn|%s' | grep 'your_search_info'

%H: commit hash
%cn: committer name
%s: subject

git commit

修改 commit 信息

用一条新的 commit 信息修订现有的 commit,这会覆盖原始 commit。请勿在已推送的 commit 中使用它。

1
git commit --amend -m "<new commit message>"

恢复指定 diff

1
2
// You can specifically apply an out-of-date diff or a diff which was never attached to a revision by using this flag.
arc patch --diff diff_id --nobranch

删除多个本地 branches

1
2
# 执行前需要切换到master分支执行
git branch | grep -v "master" | xargs git branch -D

如何把分支比较结果输入到指定文件

  • Linux 输出重定向
1
2
> 输出重定向:会将原来的文件内容覆盖。
>> 追加:不会覆盖原来文件的内容,而是追加到文件的尾部。
1
2
3
4
# 使用 Linux 重定向命令
git diff [branchA] [branchB] >>d:/diff/exportname.diff # 追加

git diff [branchA] [branchB] >d:/diff/exportname.diff # 覆盖

git patch

有时候,我们需要进行代码迁移,比如把 A 开发机上的代码迁移到 B 开发机上,这时候就可以使用补丁。

git 提供两种补丁方案: - 通过 git diff 生成 .diff 文件。 * 可以指定文件生成 .diff 文件,也可以指定单个或多个 commit 生成。 * 生成的文件不含有 commit 信息。 - 通过 git format-patch 生成 .patch 文件。 * 一个 commit 对应一个 patch 文件。 * 生成的文件含有 commmit 信息。

git format-patch

1
2
3
4
5
6
7
8
# 当前分支所有超前 master 的提交
git format-patch -M master

# 某次提交以后的所有 patch。[commit id] 指的是 commit name,可以通过 git log 查看。
git format-patch [commit id]

# 某两次提交之间的所有patch:
git format-patch [commit sha1 id..[commit sha2 id]

git format-patch 命令中,一个 commit 对应一个 patch 文件,所以生成的补丁文件默认从 1 开始顺序编号,并使用对应提交信息中的第一行作为文件名。

apply patch

1
2
3
4
5
6
7
8
# 先检查 patch 文件
git apply --stat xxx.patch

# 检查能否应用成功
git apply --check xxx.patch

# 打补丁。使用 -s 或 –-signoff 选项,可以 commit 信息中加入 signed-off-by 信息。
git am --signoff < xxx.patch
  • branch 中修改文件所在目录,git 是可以跟踪这个变化的。

git submodule

有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目。 也许是第三方库,或者你独立开发的,用于多个父项目的库。 现在问题来了:你想要把它们当做两个独立的项目,同时又想在一个项目中使用另一个。

Git 通过子模块来解决这个问题。 子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。

在配置网站的 gitHun Actions 中,主题 Next 是一个 submodule。我将 Next submodule 转化为普通文件夹,步骤如下所示。

1

如何把 Git Submodule 变成普通文件夹

References

近年来互联网数据大爆炸,数据的丰富度和覆盖面远远超出人工可以观察和总结的范畴,而机器学习的算法能指引计算机在海量数据中,挖掘出有用的价值,也使得无数学习者为之着迷。

机器学习是什么

在我看来,机器学习研究的是计算机怎样模拟人类的学习行为,以获取新的知识或技能,并重新组织已有的知识结构使之不断改善自身。简单来讲,就是计算机从数据中学习出规律和模式,以应用在新数据上做预测的任务。

机器学习关注什么问题

并非所有的问题都适合用机器学习解决 (比如逻辑清晰的问题用规则就能很高效和准确地处理),也没有一个机器学习算法可以通用于所有问题。那么,机器学习,到底是关心和解决什么样的问题。

如果在 IT 行业 (尤其是互联网) 里溜达一圈,你会发现机器学习在以下热点问题中有广泛应用:

从功能的角度分类,机器学习在一定量级的数据上,可以解决下列问题:

  • 分类问题:根据数据样本上抽取出的特征,判定其属于有限个类别中的哪一个。比如:垃圾邮件识别。

  • 回归问题:根据数据样本上抽取出的特征,预测一个连续值的结果。比如:电影票房预测。

  • 聚类问题:根据数据样本上抽取出的特征,让样本抱团 (相近 / 相关的样本在一团内)。比如:新闻分类。

其实,上述常见问题可以划到机器学习最典型的 2 个分类上:

  • 分类与回归问题需要用已知结果的数据做训练,属于 “监督学习”。

  • 聚类的问题不需要已知标签,属于 “非监督学习”。

入门方法与学习路径

机器学习对大多数入门者也有一个比较通用的学习路径,也有一些优秀的入门资料可以降低大家的学习门槛。简单说来,大概的一个学习路径如下:

因为机器学习是一个将数学 / 算法理论和工程实践紧密结合的领域,需要扎实的理论基础帮助引导数据分析与模型调优,同时也需要精湛的工程开发能力去高效化地训练和部署模型和服务,所以最左边之所以列了『数学基础』、『典型机器学习算法』、『编程基础』三个并行的部分。

数学基础

机器学习之所以相对于其他开发工作,更有门槛的根本原因就是数学。每一个算法,要在训练集上最大程度拟合同时又保证泛化能力,需要不断分析结果和数据,调优参数,这需要我们对数据分布和模型底层的数学原理有一定的理解。

如果只是想合理应用机器学习,而不是做相关方向的理论研究,需要的数学知识基本都集中在微积分、线性代数、概率与统计中。

典型算法

机器学习里所说的 “算法” 与程序员所说的 “数据结构与算法分析” 里的 “算法” 略有区别。前者更关注结果数据的召回率、精确度、准确性等方面,后者更关注执行过程的时间复杂度、空间复杂度等方面。

绝大多数问题用典型机器学习的算法都能解决,粗略地列举一下这些方法如下:

基本工作流程

当我们基本具备了机器学习的必要条件后,剩下的就是怎么运用它们去做一个完整的机器学习项目。

机器学习的工作流程如下:抽象成数学问题 - 获取数据 - 特征预处理与特征选择 - 训练模型与调优 - 模型诊断 - 模型融合 - 上线运行。

这些工作流程主要是工程实践上总结出的一些经验。并不是每个项目都包含完整的一个流程。这里的部分只是一个指导性的说明,只有大家自己多实践,多积累项目经验,才会有自己更深刻的认识。

参考资料

对泰山的向往,要从课本说起,从冯骥才的《挑山工》,到杜甫的 “造化钟神秀,阴阳割昏晓”,自己对泰山的向往不断被加深,一直渴望去看朝阳从云海中喷薄而出,领略孔子登泰山而小鲁的心境。

多平台维护不易,内容实时更新于 个人网站,请移步阅读最新内容。

泰山本来是毕业旅行的一部分,中间却不断耽误和延后,工作一年多了也未成行,最后一狠心,不愿意再等待最佳的季节和时机,选择了一个秋日的周末 (2019 年 10 月 19~20 日),和女朋友从北京出发,小憩济南,夜爬泰山,圆了自己的泰山梦。

ps. 这个时间点被许多人劝说天气比较冷,不适合夜爬,结果自己做足攻略和准备后,一趟下来,发现并不是别人描述的那么寒冷和危险,每个人对冷暖、风险的感受不同,所以小马过河,深浅还是需要自己试。

本次路线规划的特点:

  • 适合上班族和学生,占用周末时间,不影响周末晚上的休息,周一工作和学习元气满满。

  • 密集游览济南 (趵突泉、大明湖和芙蓉街) 和泰山 (泰山和岱庙) 的主要景点。

  • 浏览时间分散,休息时间比较充分,不会特别累。

  • 两个人同行,旅行花销 (交通、食宿、门票) 不到 1400 元。途中高铁、打车较多,外加一晚的住宿,整体花销多一点。

2019 年 10 月 18 日 (周五) 晚上,和女朋友乘坐 K101 火车从北京出发,在火车上休息。第二天早上五点一刻抵达济南站,火车站附近寄存行李 (10 元钱),我们轻装简行,徒步前往趵突泉景点 (离车站 3 公里),沿途可以看济南的景色,感受生活气息,以及解决早饭,抵达趵突泉景点的时间正好是开园时间 (7:00),门口微信购票,园内游客比较少,不用人挤人地排队等待。

景点的清晨,地面湿漉漉的,空气很适宜,旁边有不少本地人在晨练。

趵突泉位于景区的深处,三眼泉水喷突翻滚,旁边小泉串串珍珠,不愧是 “泉水甲天下”。我们到达的时间比较早,游客很少,拍照和欣赏景色很方便,所以建议先游趵突泉,后看大明湖,错峰出行

园内除了趵突泉,周边也是百泉争涌,各有特点,时间充裕可以看看,这些泉水先会流到济南的护城河,最终流向大明湖畔,“四面荷花三面柳,一城山色半城湖”,正是这个城市的写照。我们在趵突泉景点看得比较细,逗留的时间比较长,大概用时 2 小时。

浏览完趵突泉后,向北 800 米可以到达芙蓉街 (小吃街),芙蓉街已经被全国各地的美食和网红食品占据,本地有特色的食品并不多,所以我匆匆路过,没有在这里停留,去看大明湖,哈哈。

从芙蓉街出来后,继续向北,便能到达大明湖。走在湖边,湖光潋滟,秋风阵阵,很是惬意,自己绕湖行走一圈,大概用时 1.5 小时。

大明湖的荷花还是蛮多的,但是秋季的时节不对,荷花已经盛开过,茂盛的荷叶依旧可以让我想象出荷花布满湖面的美景。

从大明湖出来后,时间略微有点紧,打车返回济南站,然后乘坐 G459 去泰安 (泰山所在地)。

济南旅游建议:

  • 趵突泉旁边的小亭,有免费的泉水品尝,清冽甘美。

  • 抵达趵突泉后,门口有自助买票 (成人 40 元),不用排队。

  • 济南的趵突泉、大明湖和芙蓉街都聚在中心区,离济南站比较近,离济南西站比较远,建议买票到济南站,而非济南西站。

从济南出发,高铁不到半小时就能抵达泰安。我们打车抵达岱庙附近的酒店,稍作休息,然后游览岱庙。

ps. 网上攻略说泰山出租车不打卡,自己不喜欢搞价,所以整个行程一直选择滴滴打车,避免被黑出租坑和不必要的搞价。


岱庙是历代帝王举行封禅大典和祭拜泰山神的地方,园内碑林众多,一部分是泰山上的石刻复制,文化底蕴很厚实,需要静下心慢慢体会。

岱庙对古石刻和壁画的保护并不到位,好多石刻裸露在外,仍有游客对壁画拍照,遗憾。岱庙周边的城墙对游客开放,可以登上城墙绕行一圈,瞭望远处的泰山。自己对碑文看得略微细一点,时间稍微长点,游览时间大概 1.5 小时。岱庙和泰山的门票是共用的 (成人 115 元,三日内不限次数),可以微信公众号购票,景区身份证验票。

下午五点半游览完岱庙后,回到酒店休息,为晚上的夜爬储能。晚上 10:30 醒来,点外卖吃晚饭,然后打车直接到红门登山口,开始泰山的夜爬之行。

因为游览岱庙时已经买好了泰山和岱庙的通票,直接刷身份证进入景区,比排在外面买纸质票方便许多。我们大概是凌晨零点从红门开始爬山,同行爬泰山的游客很多,整个行程周围 10 米内基本会一直有同行者,很热闹,不用担心独行夜路。刚从红门上来时,道路中间会摆放一些财神塑像,注意安全。

泰山夜行路线比较成熟,一路上提供矿泉水、方便面、爬山杖、军大衣的商家比比皆是,完全不用担心错过这家没下家。到达中天门后,继续向前走 200 米左右,会有一个比较便宜的补给区 (中天门附近车辆运输方便),比如矿泉水 10 元 4 瓶,如果继续向上爬,价格就不会那么便宜了,所以建议在中天门适度补给。因为是夜间,水的需求量应该不会太多,不建议购买太多背上去 (推荐 1 瓶 / 人),可以自带一些热水。此外,夜间爬山时运动量大,不会太冷,所以不建议开始爬山时租军大衣,否则爬山时不方便,归还时也不方便,建议爬到南天门后再租军大衣。

夜爬泰山看不清远处,所以低着头一步一个脚印向前走,反而简单起来。我们在爬山时,中间有半个多小时的休息,抵达南天门时已经 4 点半 (从入口开始算起,大概花费 4.5 小时)。南天门的风明显变大,气温也比较低,那里可以租军大衣 (租金 10/20/30 元不等,押金 100 元,返还衣服时退押金)。我们在那里才穿上背了一路的羽绒服 (夜爬真心不冷),外面套着租的军大衣,全副武装抗冷。

整装完毕后,便可以看时间提早去日观峰挑个好位置,观鲁台也可以。从南天门到观日出的好地点 — 日观峰 (拱北石),大概需要半小时,建议至少比日出时间提早一小时到,可以占个好地方,否则只能在别人的手机里看日出啦。我们提早一小时抵达时,天还很暗,但日观峰上已经是 people mountain people sea,大家翘首以待。

我们在寒风里等待了一个多小时,但这次太阳有点害羞,躲在云里迟迟不肯出来 (多云天气),大概 7 点多才露个脸,把大家乐得不行,也算是不枉夜爬吧。虽然没有看到朝阳从云海里喷薄而出,但是自己和一堆人盯着远处看足 2 个小时,从天黑到蒙蒙亮,到泛起鱼肚白,再到最后的亮堂堂,看天上云卷云舒,也算是一次很值得回忆的观日活动吧。

看完日出后,去旁边的玉皇顶登上最高处,一览众山小,便开始往回折返。我们第一次选择的是比较成熟的红门路线,路线大概是岱庙 -> 岱宗坊 -> 红门宫 -> 万仙楼 -> 斗母宫 -> 经石峪 -> 壶天阁 -> 回马岭 -> 中天门 -> 快活三里 -> 云步桥 -> 五大夫松 -> 十八盘 -> 南天门 -> 天街 -> 碧霞祠 -> 唐摩崖 -> 五岳独尊 -> 日观峰 -> 玉皇顶。

因为晚上夜爬无法看清楚风景,所以自己选择原路折返,一路下坡,从高处看着下面曲折的山道,感慨自己是如何登上来的,正所谓 “登高必自卑,行远必自迩”。我们走到中天门时,因为女朋友比较累,所以在那里乘坐景区的摆渡车下山 (30 元 / 人) 到天外村,大概中午 11 点半到达山脚。

泰山旅游建议:

  • 预定的酒店最好在岱庙附近,距离岱庙和泰山登山口都比较近,方便出游。

  • 夜爬泰山,晚上记得要吃好饭,下一顿饭估计要清晨了。看完日常后,在天街有几家 10 元管饱的早餐,但是不太卫生,我亲眼看到服务员会把其他人吃剩的咸菜重新放回去。

  • 最好轻装简行,记得拿充电宝,拿点热水和士力架,不要带太多的零食。山上网络不好,可以带一些现金。

  • 虽然路上游客比较多,但是很多路段没有灯,建议购买头灯或手电筒,偶尔借着灯光看看远处,也是不错的体验。带上头灯,你一定是泰山最亮的仔。

  • 泰山光污染不严重,天气晴朗时,抬头应该可以看到月亮和繁星。

  • 夜爬注意安全,泰山最抖的是十八盘路段,尤其是升仙坊这一段,记得抓好路旁边的扶手。

  • 路上小贩特别多,买东西一定不要在第一家买,对半还价。尽管我做了攻略,也深谙这个道理,但是饥饿和寒冷让我一次次忘记,比如我在中天门第一家买的西瓜很贵,继续行走 200 米,有一排商家,可以便宜一大半,租大衣同理。

  • 记得买保险,比如支付宝的旅游险,一般是三日,可以覆盖自己的短期游。

中午在酒店修整后,2 点出门吃午饭,乘坐 4 点多的 G322 从泰安高铁站返回北京,到北京大概是晚上 6 点半,可以美美休息一晚,第二天依然是精气神饱满。

ps. 本文实时更新于 个人网站,请移步阅读。

国内的网盘虽然免费,但总让人对隐私不太放心,毕竟 “免费的永远是最贵的”。

自己之前购买了一个 VPS,搭建自己的网站后,感觉没有充分利用 VPS 的流量和性能,于是琢磨搭建一个私人的云服务,随后就发现了 Nextcloud 这一开源云服务。

通过 链接 注册并购买搬瓦工 VPS,就可以按下面的教程安装 NextCloud 私人云盘啦,我也可以得到新客注册的返现。

About NextCloud

Nextcloud is the open source file sync and share software for everyone from individuals to large enterprises and service providers. Nextcloud provides a safe, secure and compliant file sync and share solution on servers you control.
With Nextcloud you can share one or more folders on your PC, and sync them with your Nextcloud server. Place files in your local shared directories, and those files are immediately synced to the server, and then to other PCs via the desktop client. Not near a desktop client? No problem, simply log in with the web client and manage your files there. The Android and iOS mobile apps allow you to browse, download and upload photos and videos.
Whether using a mobile device, a workstation, or a web client, Nextcloud provides the ability to put the right files in the right hands at the right time on any device in one simple-to-use, secure, private and controlled solution.

简而言之,Nextcloud 是一个自由及开放源代码的私有云网盘,每个人都可以在私人服务器上安装并运行它,能够快速同步你的文件到你的私有服务器,方便你跨平台 (现在支持 PC、Android 和 iOS) 同步和分享文件,功能和百度云不差多少,优点是隐私好,同步下载速度取决于服务器带宽。

与 Dropbox 等专有服务相比,Nextcloud 的开放架构让用户可以利用应用程序的方式在服务器上新增额外的功能,并让用户可以完全掌控自己的数据。同时,Nextcloud 可与在 Windows、macOS 或是多种 Linux 发布版上运行的客户端同步。

Nextcloud 用户可以管理日历、联系人、计划工作与流媒体。此外,用户也可以在 Nextcloud 上使用基于浏览器的文本编辑器、书签服务、缩略网址服务、相册、RSS 阅读器与文件查看器。因为有良好的扩展性,Nextcloud 可以透过鼠标点一下即可完成安装的应用程序强化其功能,并可连线至 Dropbox、Google 云端硬盘与 Amazon S3 等产品。

安装简介

Nextcloud 虽然这么好用,但是安装依赖却非常复杂,需要安装 LNMP 集成环境 (i.e. Linux + Nginx + MySql + PHP),在搭建过程中或多或少都会出点问题。

本文推荐一个很方便的安装方法 docker-nextcloud,使用纯命令形式在 Docker 上安装 NextCloud (Docker file 会帮你把负责的依赖都配置好),并探讨如何配置反向代理,适合尝鲜的新手。

安装 Docker 后,需要安装两个容器:mysql 和 nextcloud。其中,mysql 用于存储用户的数据,nextcloud 通过向 mysql 容器读写数据,从而实现数据的存储和访问。

安装 Docker

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux 或 Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

1
2
3
4
# CentOS 7、Debian、Ubuntu
curl -sSL https://get.docker.com/ | sh
systemctl start docker
systemctl enable docker

复习知识点

  • curl 是一个工具,用于传输来自服务器或者到服务器的数据。
  • systemctl 是一个系统管理守护进程、工具和库的集合,用于取代 system V、service 和 chkconfig 命令,初始进程主要负责控制 systemd 系统和服务管理器。
  • systemctl start 启动服务
  • systemctl enable 激活服务并在开机时启用

安装 Nextcloud 服务器

1
2
3
4
5
6
7
8
# 拉取 Mysql 镜像和 Nextcloud 镜像
docker pull rootlogin/nextcloud && docker pull mariadb:10

# 创建 mysql 容器,注意修改数据库信息
docker run --name nextcloud_db -d --restart=always -e MYSQL_ROOT_PASSWORD=test -e MYSQL_DATABASE=test -e MYSQL_USER=test -e MYSQL_PASSWORD=test -v /var/nextcloud/mysql:/var/lib/mysql mariadb:10

# 创建 nextcloud 容器,添加链接到 mysql 容器;ip 是浏览器访问云盘的端口号。使用镜像 rootlogin/nextcloud,以后台模式启动一个容器, 容器命名为 nextcloud,将容器的 80 端口映射到主机的 3000 端口,主机的目录 /var/nextcloud/data 映射到容器的 /data,并添加链接到上述的 nextcloud_db 容器。
docker run --name nextcloud_db -d --restart=always -e MYSQL_ROOT_PASSWORD=test -e MYSQL_DATABASE=test -e MYSQL_USER=test -e MYSQL_PASSWORD=test -v /var/nextcloud/mysql:/var/lib/mysql mariadb:10

MariaDB 和 MySQL 的关系:MariaDB 数据库管理系统是 MySQL 的一个分支。开发这个分支的原因之一是:甲骨文公司收购了 MySQL 后,有将 MySQL 闭源的潜在风险,因此社区采用分支的方式来避开这个风险。
MariaDB 的目的是完全兼容 MySQL,包括 API 和命令行,使之能轻松成为 MySQL 的代替品。

 

恭喜你,现在初级版的云服务器已经搭建成功。访问地址为 http://your_ip:3000。
启动命令里的 3000 端口可自行替换,不过后面有关端口的命令都可自行修改,/var/nextcloud/data 为网盘的数据库,可以自行修改。

复习知识点

  • docker pull 是从镜像仓库拉取镜像。
  • docker run 是创建一个新的容器并运行一个命令。
  • --restart=always,设置开机重启

防火墙开启端口

1
2
3
#CentOS 7
firewall-cmd --zone=public --add-port=3000/tcp --permanent
firewall-cmd --reload

初始设置

  • 访问 http://your_ip:3000。
  • 创建管理员帐号和密码
  • 数据库选择 MySQL/MariaDB,如果配置不成功,可以选择 SQLite (性能差点,但是可以满足个人基本的需求)。
名称
用户名 test
密码 test
数据库名 test
地址 nextcloud_db:3306

mysql 数据库默认端口是 3306。

  • 恭喜你,进入自己的网盘界面。

域名访问

IP 访问会直接把云盘的 IP 和端口暴露出来,感觉不太妥。如果要通过域名访问自己的网盘,就需要反代了。

反代可以用 Nginx、Apache、Caddy,本文讲述如何使用 Nginx。

Nginx 是一款轻量级的 Web 服务器 / 反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在 BSD-like 协议下发行。其特点是占有内存少,并发能力强,

默认用户已经完成购买域名、安装 Nginx 的前序步骤,鼓励折腾一下,有问题欢迎下面留言交流。

certbot 生成 https 证书

Let's Encrypt 是很火的一个免费 SSL 证书发行项目,自动化发行证书,证书有 90 天的有效期。适合个人使用或者临时使用,不用再忍受自签发证书不受浏览器信赖的提示。
附上 CentOS 7.2 的 免费 SSL 证书 Let's Encrypt 流程。

1
./certbot-auto certonly --email your_mail --agree-tos --no-eff-email --webroot -w /var/nextcloud -d drive.example.com

配置 Nginx 配置文件

在 /etc/nginx/conf.d/ 下的配置文件里添加如下配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server {
listen 80;
listen [::]:80;
server_name drive.example.com;
# enforce https
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name drive.example.com;

ssl_certificate /etc/letsencrypt/live/drive.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/drive.example.com/privkey.pem;

add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

location / {
proxy_pass http://your_ip:3000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

最后,重启 nginx,就可以通过网址访问自己的云盘啦!

1
systemctl restart nginx

安装中可能遇到的问题 FQA

  • Q: 初始化时,提示 “看起来您正在尝试重新安装您的 Nextcloud。但您的 config 文件夹中没有 CAN_INSTALL 文件。请在您的 config 文件夹中创建 CAN_INSTALL 文件以继续。”
  • A: 运行如下命令。
1
cd /var/nextcloud/data/config && touch CAN_INSTALL

其中,/var/nextcloud/data 为网盘的数据库,请自行修改。


  • Q: 反向代理后,网址无法直接访问,比如提示 403。
  • A:请先定位问题,可以在 /var/log/nginx/error.log 查看代理错误。

  • Q: 关机重启后,原来配置好的网盘无法访问。
  • A: 在使用 docker run 启动容器时,已经使用 --restart 参数来设置容器开机自启。如果发现服务器重启后,无法访问网盘,可以尝试 update 命令设置 --restart=always。
1
docker update --restart=always 容器名称

Docker 提供了 restart policy 机制,可以在容器退出或者 Docker 重启时控制容器能够自启动。这种 Restart policy 可以保证相关容器按照正确顺序启动。


  • Q: 通过 IP 方式 登录时,没有出现登录界面,显示 "HTTP ERROR 500".
  • A: 根据 Nextcloud 12 HTTP Error 500 提供的方法,更新 PHP 模块可以解决问题。
    • 我使用 apt-get upgrade 升级了所有软件的版本,然后问题得到修复。

HTTP 500 错误,全称为 HTTP 500 Internal Server Error,即 HTTP 500 内部服务器错误。HTTP 500 内部服务器错误表示服务器遇到意外情况,导致其无法履行请求,但它无法说明具体错误或发生错误的根本原因。当发生错误时,访问的网站会显示发生错误。

ps. 本文实时更新于个人网站,请移步阅读。

Gif 是当下较为流行的一种交流方式,其文件比视频小,而且比 jpg 图片生动形象,所以不仅在微薄、QQ 等社交中尤为常见,而且适用于产品和功能的展示。同时,Gif 文件大小一般是普通 MP4 格式的数倍。

GIFs are an average of 5-10 times larger than an efficiently encoded MP4 video. This difference in size means that GIFs waste a large amount of bandwidth and also load at a slower rate leading to a bad user experience.

下文主要分享下如何在 Ubuntu 18 上录制 gif 动画以及处理 gif 文件,不必动用到 Windows 中像 Photoshop 这样的神器。

软件需求

  • ImageMagick > ImageMagick 是一款用于创建、编辑和合并位图图像的一款开源软件。
  • byzanz > byzanz 是通过输入命令方式来录制文件小、清晰的 GIF 动态效果图。

Gif 录制

本文使用 byzanz 来录制 Gif,其主要的参数选项有:

参数 单位 含义
-d, --duration SECS 动画的时间 (默认:10 秒)
--delay SECS 开始之前的延时 (默认:1 秒)
-c, --cursor 录制鼠标光标
-a, --audio 录音
-x, --x 像素 要录制矩形的 X 坐标
-y, --y 像素 要录制矩形的 Y 坐标
-w, --width 像素 录制矩形的宽度
-h, --height 像素 录制矩形的高度
-v, --verbose 详细
--display 要使用的 X 显示

例子

1
byzanz-record -d 10 --delay=5 -x 0 -y 0 -w 1440 -h 900 out.gif  

上面的命令是录制屏幕坐标 (0,0) 处宽度 1440 像素、高度 900 像素的矩形区域 (指定的坐标为矩形左上角),延时 5 秒开始录制,录制时间 10s,输出文件 out.gif。

Gif 合并

如果想将录制的多个 Gif 合并成一个文件,只需将要合并的文件存到同一文件夹当中,再执行如下命令即可,不需要安装其他软件,Ubuntu 比 Windows 强大之处。

1
convert -delay 120 -loop 0 *.gif output.gif

其中,"-delay 120" 表示 Gif 动画速度,"-loop 0" 表示无限循环。

参考文献

Record Screen as Animated GIF in Ubuntu with Byzanz

Gifs vs animated videos - which should you use

0%